library(swimplot) library(coxphf) library(grid) library(gtable) library(readr) library(mosaic) library(dplyr) library(survival) library(survminer) library(ggplot2) library(scales) library(coxphf) library(ggthemes) library(tidyverse) library(gtsummary) library(flextable) library(parameters) library(car) library(ComplexHeatmap) library(tidyverse) library(readxl) library(survival) library(janitor) library(openxlsx) library(writexl) library(rms) library(pROC) library(DT)

#ctDNA Detection rate by Stage and Window

#Baseline
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.Base %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.Base == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.Base, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.Base == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#C2D1
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.C2D1 %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.C2D1 == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.C2D1, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.C2D1 == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#post-NAC Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postNAC %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postNAC == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postNAC, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postNAC == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#MRD Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.MRD %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.MRD == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.MRD, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.MRD == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#On-treatment
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.onACT <- factor(circ_data$ctDNA.onACT, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.onACT %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.onACT == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.onACT, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.onACT == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Surveillance Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.surveillance <- factor(circ_data$ctDNA.surveillance, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.surveillance %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.surveillance == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.surveillance, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.surveillance == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Post-ACT Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postACT <- factor(circ_data$ctDNA.postACT, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postACT %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postACT == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postACT, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postACT == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Post-relapse Window
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$ctDNA.postRelapse <- factor(circ_data$ctDNA.postRelapse, levels=c("NEGATIVE","POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("I","II","III"))
circ_data <- subset(circ_data, ctDNA.postRelapse %in% c("NEGATIVE", "POSITIVE"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.postRelapse == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.postRelapse, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.postRelapse == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Demographics Table

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data_subset <- circ_data %>%
  select(
    Age,
    Gender,
    PrimSite,
    NAC,
    NAC.Regimen,
    TRG.Mandard,
    TNM,
    Stage,
    Grade,
    Lauren.Class,
    Margins,
    ACT,
    ACT.Regimen,
    DFS.Event,
    OS.Event,
    FU.months) %>%
  mutate(
    Age = as.numeric(Age),
    Gender = factor(Gender, levels = c("Male", "Female")),
    PrimSite = factor(PrimSite, levels = c("Stomach", "G/J", "Oesophagus")),
    NAC = factor(NAC, levels = c("TRUE", "FALSE"), labels = c("Neoadjuvant Therapy", "Upfront Surgery")),
    NAC.Regimen = factor(NAC.Regimen),
    TRG.Mandard = factor(TRG.Mandard, levels = c("TRG1","TRG2", "TRG3", "TRG4", "TRG5")),
    TNM = factor(TNM, levels = c("T0-TisN0M0","T1-T2N0", "T2-T3N0-N1", "T2N1-N2", "T3N2-N3", "T4N0-N1", "T4N2-N3")),
    Stage = factor(Stage, levels = c("0","I","II", "III")),
    Grade = factor(Grade, levels = c("G1", "G2", "G3")),
    Lauren.Class = factor(Lauren.Class),
    Margins = factor(Margins, levels = c("R0", "R1")),
    ACT = factor(ACT, levels = c("TRUE", "FALSE"), labels = c("Adjuvant Treatment", "Observation")),
    ACT.Regimen = factor(ACT.Regimen),
    DFS.Event = factor(DFS.Event, levels = c("TRUE", "FALSE"), labels = c("Recurrence", "No Recurrence")),
    OS.Event = factor(OS.Event, levels = c("TRUE", "FALSE"), labels = c("Deceased", "Alive")),
    FU.months = as.numeric(FU.months))
table1 <- circ_data_subset %>%
  tbl_summary(
    statistic = list(
      all_continuous() ~ "{median} ({min} - {max})",
      all_categorical() ~ "{n} ({p}%)")) %>%
  bold_labels()
table1
Characteristic N = 621
Age 66 (34 - 86)
Gender
    Male 39 (63%)
    Female 23 (37%)
PrimSite
    Stomach 38 (61%)
    G/J 24 (39%)
    Oesophagus 0 (0%)
NAC
    Neoadjuvant Therapy 55 (89%)
    Upfront Surgery 7 (11%)
NAC.Regimen
     7 (11%)
    Chemoimmunotherapy 7 (11%)
    Chemotherapy 47 (76%)
    Radiotherapy 1 (1.6%)
TRG.Mandard
    TRG1 3 (5.5%)
    TRG2 8 (15%)
    TRG3 21 (38%)
    TRG4 16 (29%)
    TRG5 7 (13%)
    Unknown 7
TNM
    T0-TisN0M0 3 (4.8%)
    T1-T2N0 16 (26%)
    T2-T3N0-N1 17 (27%)
    T2N1-N2 2 (3.2%)
    T3N2-N3 8 (13%)
    T4N0-N1 9 (15%)
    T4N2-N3 7 (11%)
Stage
    0 3 (4.8%)
    I 16 (26%)
    II 26 (42%)
    III 17 (27%)
Grade
    G1 11 (28%)
    G2 21 (53%)
    G3 8 (20%)
    Unknown 22
Lauren.Class
     5 (8.1%)
    Diffuse 18 (29%)
    Intestinal 34 (55%)
    Mixed 5 (8.1%)
Margins
    R0 61 (98%)
    R1 1 (1.6%)
ACT
    Adjuvant Treatment 53 (85%)
    Observation 9 (15%)
ACT.Regimen
     9 (15%)
    Chemoimmunotherapy 4 (6.5%)
    Chemotherapy 48 (77%)
    Immunotherapy 1 (1.6%)
DFS.Event
    Recurrence 29 (47%)
    No Recurrence 33 (53%)
OS.Event
    Deceased 19 (31%)
    Alive 43 (69%)
FU.months 29 (2 - 93)
1 Median (Range); n (%)
fit1 <- as_flex_table(
  table1,
  include = everything(),
  return_calls = FALSE,
  strip_md_bold = TRUE)
Warning: The `strip_md_bold` argument of `as_flex_table()` is deprecated as of gtsummary 1.6.0.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
fit1

Characteristic

N = 621

Age

66 (34 - 86)

Gender

Male

39 (63%)

Female

23 (37%)

PrimSite

Stomach

38 (61%)

G/J

24 (39%)

Oesophagus

0 (0%)

NAC

Neoadjuvant Therapy

55 (89%)

Upfront Surgery

7 (11%)

NAC.Regimen

7 (11%)

Chemoimmunotherapy

7 (11%)

Chemotherapy

47 (76%)

Radiotherapy

1 (1.6%)

TRG.Mandard

TRG1

3 (5.5%)

TRG2

8 (15%)

TRG3

21 (38%)

TRG4

16 (29%)

TRG5

7 (13%)

Unknown

7

TNM

T0-TisN0M0

3 (4.8%)

T1-T2N0

16 (26%)

T2-T3N0-N1

17 (27%)

T2N1-N2

2 (3.2%)

T3N2-N3

8 (13%)

T4N0-N1

9 (15%)

T4N2-N3

7 (11%)

Stage

0

3 (4.8%)

I

16 (26%)

II

26 (42%)

III

17 (27%)

Grade

G1

11 (28%)

G2

21 (53%)

G3

8 (20%)

Unknown

22

Lauren.Class

5 (8.1%)

Diffuse

18 (29%)

Intestinal

34 (55%)

Mixed

5 (8.1%)

Margins

R0

61 (98%)

R1

1 (1.6%)

ACT

Adjuvant Treatment

53 (85%)

Observation

9 (15%)

ACT.Regimen

9 (15%)

Chemoimmunotherapy

4 (6.5%)

Chemotherapy

48 (77%)

Immunotherapy

1 (1.6%)

DFS.Event

Recurrence

29 (47%)

No Recurrence

33 (53%)

OS.Event

Deceased

19 (31%)

Alive

43 (69%)

FU.months

29 (2 - 93)

1Median (Range); n (%)

save_as_docx(fit1, path= "~/Downloads/table1.docx")

#Heatmap with Clinical & Genomics Factors

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data %>% arrange(Stage)
circ_datadf <- as.data.frame(circ_data)

ha <- HeatmapAnnotation(
  Stage = circ_data$Stage,
  Gender = circ_data$Gender,
  PrimSite = circ_data$PrimSite,
  NAC = circ_data$NAC,
  ACT = circ_data$ACT,
  ctDNA.Base = circ_data$ctDNA.Base,
  ctDNA.C2D1 = circ_data$ctDNA.C2D1,
  ctDNA.postNAC = circ_data$ctDNA.postNAC,
  ctDNA.MRD = circ_data$ctDNA.MRD,
  ctDNA.surveillance = circ_data$ctDNA.surveillance,
  DFS.Event = circ_data$DFS.Event,
  OS.Event = circ_data$OS.Event,
  
  col = list(Stage = c("0" = "seagreen1", "I" = "seagreen1", "II" = "orange", "III" = "purple"),
    Gender = c("Female" = "goldenrod" , "Male" = "blue4"),
    PrimSite = c("Stomach" = "brown", "G/J" = "darkgreen", "Oesophagus" = "orange4"),
    NAC = c("FALSE" = "cornflowerblue", "TRUE" ="darkmagenta"),
    ACT = c("TRUE" = "brown4", "FALSE" ="khaki"),
    ctDNA.Base = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.C2D1 = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.postNAC = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.MRD = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.surveillance = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    DFS.Event = c("TRUE" = "red3", "FALSE" ="blue"),
    OS.Event = c("TRUE" = "black", "FALSE" ="gray")
)
)
ht <- Heatmap(matrix(nrow = 0, ncol = length(circ_data$Stage)),show_row_names = FALSE,cluster_rows = F,cluster_columns = FALSE, top_annotation = ha)
pdf("heatmap.pdf",width = 7, height = 7)
draw(ht, annotation_legend_side = "bottom")
dev.off()
null device 
          1 

#Overview Plot

setwd("~/Downloads") 
clinstage<- read.csv("PLAGAST_OP.csv")
clinstage_df<- as.data.frame(clinstage)

#Display the swimmer plot with the label box
oplot<-swimmer_plot(df=clinstage_df,
                    id='PatientName',
                    end='fu.diff.months',
                    fill='gray',
                    width=.01,)
oplot <- oplot + theme(panel.border = element_blank())
oplot <- oplot + scale_y_continuous(breaks = seq(-12, 96, by = 6))
oplot <- oplot + labs(x ="Patients" , y="Months from Surgery")
oplot



##plot events
oplot_ev1 <- oplot + swimmer_points(df_points=clinstage_df,
                                    id='PatientName',
                                    time='date.diff.months',
                                    name_shape ='Event_type',
                                    name_col = 'Event',
                                    size=3.5,fill='black',
                                    #col='darkgreen'
)
oplot_ev1
Warning: Removed 114 rows containing missing values or values outside the scale range (`geom_point()`).

#Shape customization to Event_type

oplot_ev1.1 <- oplot_ev1 + ggplot2::scale_shape_manual(name="Event_type",values=c(1,16,6,18,4),breaks=c('ctDNA_neg','ctDNA_pos','Imaging','Surgery','Death'))

oplot_ev1.1
Warning: Removed 114 rows containing missing values or values outside the scale range (`geom_point()`).

#plot treatment

oplot_ev2 <- oplot_ev1.1 + swimmer_lines(df_lines=clinstage_df,
                                         id='PatientName',
                                         start='Tx_start.months',
                                         end='Tx_end.months',
                                         name_col='Tx_type',
                                         size=3.5,
                                         name_alpha = 1.0)
oplot_ev2 <- oplot_ev2 + guides(linetype = guide_legend(override.aes = list(size = 5, color = "black")))
oplot_ev2  
Warning: Removed 114 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 405 rows containing missing values or values outside the scale range (`geom_segment()`).

#colour customization
oplot_ev2.2 <- oplot_ev2 + ggplot2::scale_color_manual(name="Event",values=c( "purple","black","black", "lightblue", "green", "red", "blue","orange"))
oplot_ev2.2
Warning: Removed 114 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 405 rows containing missing values or values outside the scale range (`geom_segment()`).

#RFS by ctDNA at Baseline - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 17      5     NA    42.1      NA
ctDNA.Base=POSITIVE 39     20   22.3    13.3      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA Baseline | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000       11.000        4.000        0.756        0.106        0.473        0.901 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      13.0000      19.0000       0.4772       0.0849       0.3057       0.6301 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 56, number of events= 25 

                     coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.BasePOSITIVE 0.9196    2.5082   0.5030 1.828   0.0675 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE     2.508     0.3987    0.9359     6.722

Concordance= 0.604  (se = 0.041 )
Likelihood ratio test= 3.92  on 1 df,   p=0.05
Wald test            = 3.34  on 1 df,   p=0.07
Score (logrank) test = 3.58  on 1 df,   p=0.06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.51 (0.94-6.72); p = 0.068"

#OS by ctDNA at Baseline - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Base, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Base, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.Base=NEGATIVE 17      4     NA    52.7      NA
ctDNA.Base=POSITIVE 39     13     NA    24.5      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Base, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA Baseline | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.Base, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Base=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      14.0000       1.0000       0.9412       0.0571       0.6502       0.9915 

                ctDNA.Base=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      17.0000      11.0000       0.6832       0.0809       0.4963       0.8129 
circ_data$ctDNA.Base <- factor(circ_data$ctDNA.Base, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.Base, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Base, data = circ_data)

  n= 56, number of events= 17 

                     coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.BasePOSITIVE 0.7361    2.0878   0.5781 1.273    0.203

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.BasePOSITIVE     2.088      0.479    0.6724     6.483

Concordance= 0.597  (se = 0.05 )
Likelihood ratio test= 1.81  on 1 df,   p=0.2
Wald test            = 1.62  on 1 df,   p=0.2
Score (logrank) test = 1.69  on 1 df,   p=0.2
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.09 (0.67-6.48); p = 0.203"

#RFS by ctDNA levels at Baseline based on median

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

# Calculate the quartiles of p_6mo_MTM
circ_data$ctDNA.Base.MTM <- as.numeric(as.character(circ_data$ctDNA.Base.MTM))
median_value <- median(circ_data$ctDNA.Base.MTM, na.rm = TRUE)
print(median_value)
[1] 0.385
# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 0.385 ~ 1,
    ctDNA.Base.MTM >= 0.385 ~ 2
  ))

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 28      8     NA      NA      NA
ctDNA.6mMTM.Q=2 28     17   14.6    9.63      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="RFS - ctDNA MTM/mL groups at Baseline", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<0.385", "MTM/mL≥0.385"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      16.0000       6.0000       0.7701       0.0831       0.5559       0.8903 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       8.0000      17.0000       0.3600       0.0954       0.1829       0.5409 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<0.385", "MTM/mL≥0.385"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 56, number of events= 25 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.6mMTM.QMTM/mL≥0.385 1.0941    2.9865   0.4331 2.526   0.0115 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥0.385     2.987     0.3348     1.278     6.979

Concordance= 0.639  (se = 0.049 )
Likelihood ratio test= 6.94  on 1 df,   p=0.008
Wald test            = 6.38  on 1 df,   p=0.01
Score (logrank) test = 7  on 1 df,   p=0.008
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.99 (1.28-6.98); p = 0.012"

#OS by ctDNA levels at Baseline based on median

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

# Calculate the quartiles of p_6mo_MTM
circ_data$ctDNA.Base.MTM <- as.numeric(as.character(circ_data$ctDNA.Base.MTM))
median_value <- median(circ_data$ctDNA.Base.MTM, na.rm = TRUE)
print(median_value)
[1] 0.385
# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 0.385 ~ 1,
    ctDNA.Base.MTM >= 0.385 ~ 2
  ))

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 28      6     NA      NA      NA
ctDNA.6mMTM.Q=2 28     11     NA    23.9      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA MTM/mL groups at Baseline", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<0.385", "MTM/mL≥0.385"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      19.0000       3.0000       0.8914       0.0592       0.6999       0.9637 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      12.0000       9.0000       0.6444       0.0976       0.4216       0.7997 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<0.385", "MTM/mL≥0.385"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 56, number of events= 17 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.6mMTM.QMTM/mL≥0.385 0.8713    2.3901   0.5143 1.694   0.0902 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥0.385      2.39     0.4184    0.8722     6.549

Concordance= 0.609  (se = 0.062 )
Likelihood ratio test= 3.03  on 1 df,   p=0.08
Wald test            = 2.87  on 1 df,   p=0.09
Score (logrank) test = 3.04  on 1 df,   p=0.08
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.39 (0.87-6.55); p = 0.09"

#RFS by ctDNA levels at Baseline based on AUC optimal MTM/ml level

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

#DFS.Event
circ_data <- circ_data[complete.cases(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM),]
circ_data$ctDNA.Base.MTM <- as.numeric(circ_data$ctDNA.Base.MTM)
ROC <- roc(DFS.Event ~  ctDNA.Base.MTM, data = circ_data, ci = TRUE)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
p<-ggroc(ROC,
         aes = c("linetype"), color = "blue",  size = 1,
         legacy.axes = TRUE) +
  geom_abline(color = "dark grey", size = 0.5) +
  theme_classic()+
  ylab("Sensitivity") + theme(axis.title.x = element_text(color="black", size=14), axis.title.y = element_text(color="black", size=14),axis.text.x = element_text(colour = "black", size=14),axis.text.y = element_text(colour = "black",size=14),legend.title  = element_blank(),legend.text = element_text(size=14))
Warning in ggplot2::geom_line(aes$aes, ...) :
  Ignoring unknown parameters: `aes`
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
p


#AUC
AUC <- auc(ROC)
print(AUC)
Area under the curve: 0.6529
AUC_conf <- ci.auc(ROC)
print(AUC_conf)
95% CI: 0.5062-0.7996 (DeLong)
res.roc <- roc(circ_data$DFS.Event, circ_data$ctDNA.Base.MTM)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
plot.roc(res.roc, print.auc = TRUE, print.thres = "best")


rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 0.845 ~ 1,
    ctDNA.Base.MTM >= 0.845 ~ 2
  ))

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 31      9     NA      NA      NA
ctDNA.6mMTM.Q=2 25     16   14.5    7.79      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="DFS - ctDNA MTM/mL groups at Baseline", ylab= "Disease-Free Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<0.845", "MTM/mL≥0.845"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      18.0000       7.0000       0.7544       0.0814       0.5504       0.8755 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       6.0000      16.0000       0.3267       0.0989       0.1494       0.5178 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<0.845", "MTM/mL≥0.845"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 56, number of events= 25 

                            coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.6mMTM.QMTM/mL≥0.845 1.2620    3.5325   0.4254 2.966  0.00301 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥0.845     3.533     0.2831     1.534     8.132

Concordance= 0.662  (se = 0.048 )
Likelihood ratio test= 9.29  on 1 df,   p=0.002
Wald test            = 8.8  on 1 df,   p=0.003
Score (logrank) test = 9.89  on 1 df,   p=0.002
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 3.53 (1.53-8.13); p = 0.003"

#OS by ctDNA levels at Baseline based on AUC optimal MTM/mL level

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

#OS.Event
circ_data <- circ_data[complete.cases(circ_data$OS.Event, circ_data$ctDNA.Base.MTM),]
circ_data$ctDNA.Base.MTM <- as.numeric(circ_data$ctDNA.Base.MTM)
ROC <- roc(OS.Event ~  ctDNA.Base.MTM, data = circ_data, ci = TRUE)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
p<-ggroc(ROC,
         aes = c("linetype"), color = "blue",  size = 1,
         legacy.axes = TRUE) +
  geom_abline(color = "dark grey", size = 0.5) +
  theme_classic()+
  ylab("Sensitivity") + theme(axis.title.x = element_text(color="black", size=14), axis.title.y = element_text(color="black", size=14),axis.text.x = element_text(colour = "black", size=14),axis.text.y = element_text(colour = "black",size=14),legend.title  = element_blank(),legend.text = element_text(size=14))
Warning in ggplot2::geom_line(aes$aes, ...) :
  Ignoring unknown parameters: `aes`
p


#AUC
AUC <- auc(ROC)
print(AUC)
Area under the curve: 0.6463
AUC_conf <- ci.auc(ROC)
print(AUC_conf)
95% CI: 0.4742-0.8184 (DeLong)
res.roc <- roc(circ_data$OS.Event, circ_data$ctDNA.Base.MTM)
Setting levels: control = FALSE, case = TRUE
Setting direction: controls < cases
plot.roc(res.roc, print.auc = TRUE, print.thres = "best")


rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 11.305 ~ 1,
    ctDNA.Base.MTM >= 11.305 ~ 2
  ))

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 44      9     NA      NA      NA
ctDNA.6mMTM.Q=2 12      8   19.5    13.3      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA MTM/mL groups at Baseline", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<11.305", "MTM/mL≥11.305"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      25.0000       6.0000       0.8447       0.0594       0.6826       0.9281 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        6.000        0.500        0.144        0.208        0.736 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<11.305", "MTM/mL≥11.305"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 56, number of events= 17 

                             coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.6mMTM.QMTM/mL≥11.305 1.4951    4.4599   0.4981 3.002  0.00268 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                           exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥11.305      4.46     0.2242      1.68     11.84

Concordance= 0.66  (se = 0.06 )
Likelihood ratio test= 8.21  on 1 df,   p=0.004
Wald test            = 9.01  on 1 df,   p=0.003
Score (logrank) test = 10.71  on 1 df,   p=0.001
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.46 (1.68-11.84); p = 0.003"

#OS by ctDNA levels at Baseline based on AUC optimal MTM/mL level from RFS model

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_datadf <- as.data.frame(circ_data)

# Create a new variable based on these quartiles

circ_data$ctDNA.6mMTM.Q <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.6mMTM.Q = case_when(
    ctDNA.Base.MTM < 0.845 ~ 1,
    ctDNA.Base.MTM >= 0.845 ~ 2
  ))

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.6mMTM.Q, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.6mMTM.Q, data = circ_data)

                 n events median 0.95LCL 0.95UCL
ctDNA.6mMTM.Q=1 31      6     NA      NA      NA
ctDNA.6mMTM.Q=2 25     11     38    18.9      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.6mMTM.Q, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA MTM/mL groups at Baseline", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("MTM/mL<0.845", "MTM/mL≥0.845"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.6mMTM.Q=1 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      22.0000       3.0000       0.9021       0.0537       0.7262       0.9673 

                ctDNA.6mMTM.Q=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        9.000        9.000        0.593        0.109        0.354        0.769 
circ_data$ctDNA.6mMTM.Q <- factor(circ_data$ctDNA.6mMTM.Q, levels=c("1","2"), labels = c("MTM/mL<0.845", "MTM/mL≥0.845"))
cox_fit <- coxph(surv_object ~ ctDNA.6mMTM.Q, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.6mMTM.Q, data = circ_data)

  n= 56, number of events= 17 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.6mMTM.QMTM/mL≥0.845 1.1983    3.3146   0.5185 2.311   0.0208 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.6mMTM.QMTM/mL≥0.845     3.315     0.3017       1.2     9.158

Concordance= 0.644  (se = 0.062 )
Likelihood ratio test= 5.68  on 1 df,   p=0.02
Wald test            = 5.34  on 1 df,   p=0.02
Score (logrank) test = 5.93  on 1 df,   p=0.01
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 3.31 (1.2-9.16); p = 0.021"

#RFS by ctDNA on-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.C2D1!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C2D1=NEGATIVE 20      4     NA      NA      NA
ctDNA.C2D1=POSITIVE 21     14   13.3    6.57      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA status on-NAT | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      14.0000       3.0000       0.8400       0.0853       0.5792       0.9459 

                ctDNA.C2D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        4.000       13.000        0.342        0.109        0.146        0.550 
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1, data = circ_data)

  n= 41, number of events= 18 

                     coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.C2D1POSITIVE 1.8205    6.1750   0.5767 3.157   0.0016 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1POSITIVE     6.175     0.1619     1.994     19.12

Concordance= 0.718  (se = 0.046 )
Likelihood ratio test= 12.42  on 1 df,   p=4e-04
Wald test            = 9.97  on 1 df,   p=0.002
Score (logrank) test = 12.64  on 1 df,   p=4e-04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 6.17 (1.99-19.12); p = 0.002"

#OS by ctDNA on-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.C2D1!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C2D1=NEGATIVE 20      3     NA      NA      NA
ctDNA.C2D1=POSITIVE 21      9   24.5    14.4      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA status on-NAT | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      15.0000       1.0000       0.9500       0.0487       0.6947       0.9928 

                ctDNA.C2D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        8.000        0.586        0.114        0.335        0.771 
circ_data$ctDNA.C2D1 <- factor(circ_data$ctDNA.C2D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1, data = circ_data)

  n= 41, number of events= 12 

                     coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1POSITIVE 1.5506    4.7145   0.6795 2.282   0.0225 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1POSITIVE     4.714     0.2121     1.245     17.86

Concordance= 0.706  (se = 0.054 )
Likelihood ratio test= 6.18  on 1 df,   p=0.01
Wald test            = 5.21  on 1 df,   p=0.02
Score (logrank) test = 6.2  on 1 df,   p=0.01
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.71 (1.24-17.86); p = 0.022"

#DFS by ctDNA Clearance during NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 20     13   13.3    7.36      NA
ctDNA.C2D1.Clearance=TRUE   9      2     NA   18.20      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="RFS - ctDNA clearance C2D1", ylab= "Recurrence-Free Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        4.000       12.000        0.359        0.114        0.153        0.572 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        5.000        2.000        0.741        0.161        0.289        0.930 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 29, number of events= 15 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1.ClearanceFALSE 1.6403    5.1567   0.7649 2.144    0.032 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     5.157     0.1939     1.152     23.09

Concordance= 0.667  (se = 0.046 )
Likelihood ratio test= 6.5  on 1 df,   p=0.01
Wald test            = 4.6  on 1 df,   p=0.03
Score (logrank) test = 5.66  on 1 df,   p=0.02
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.16 (1.15-23.09); p = 0.032"

#OS by ctDNA Clearance during NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 20      8     NA    18.9      NA
ctDNA.C2D1.Clearance=TRUE   9      1     NA    38.0      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="OS - ctDNA clearance C2D1", ylab= "Overall Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        7.000        0.616        0.116        0.353        0.798 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
          24            6            0            1            0           NA           NA 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 29, number of events= 9 

                           coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.C2D1.ClearanceFALSE 1.634     5.126    1.064 1.536    0.125

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     5.126     0.1951    0.6369     41.25

Concordance= 0.669  (se = 0.047 )
Likelihood ratio test= 3.48  on 1 df,   p=0.06
Wald test            = 2.36  on 1 df,   p=0.1
Score (logrank) test = 2.92  on 1 df,   p=0.09
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.13 (0.64-41.25); p = 0.125"

#RFS by ctDNA post-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.postNAC, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.postNAC, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.postNAC=NEGATIVE 30     10     NA   21.52      NA
ctDNA.postNAC=POSITIVE 11      8   7.79    3.55      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.postNAC, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA status post-NAT | All pts", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.postNAC, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.postNAC=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      13.0000      10.0000       0.6377       0.0933       0.4269       0.7883 

                ctDNA.postNAC=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    24.00000      1.00000      8.00000      0.13636      0.12392      0.00767      0.44263 
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.postNAC, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.postNAC, data = circ_data)

  n= 41, number of events= 18 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.postNACPOSITIVE 1.6603    5.2610   0.5036 3.297 0.000978 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.postNACPOSITIVE     5.261     0.1901     1.961     14.12

Concordance= 0.669  (se = 0.052 )
Likelihood ratio test= 9.69  on 1 df,   p=0.002
Wald test            = 10.87  on 1 df,   p=0.001
Score (logrank) test = 13.08  on 1 df,   p=3e-04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.26 (1.96-14.12); p = 0.001"

#OS by ctDNA post-NAT - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.postNAC, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.postNAC, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.postNAC=NEGATIVE 30      5     NA      NA      NA
ctDNA.postNAC=POSITIVE 11      8   18.9    11.7      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.postNAC, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA status post-NAT | All pts", ylab= "Overall-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.postNAC, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.postNAC=NEGATIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000      16.0000       3.0000       0.9000       0.0548       0.7212       0.9666 

                ctDNA.postNAC=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       2.0000       7.0000       0.2273       0.1409       0.0346       0.5207 
circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.postNAC, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.postNAC, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.postNACPOSITIVE 1.9944    7.3479   0.5811 3.432 0.000599 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.postNACPOSITIVE     7.348     0.1361     2.352     22.95

Concordance= 0.711  (se = 0.07 )
Likelihood ratio test= 11.82  on 1 df,   p=6e-04
Wald test            = 11.78  on 1 df,   p=6e-04
Score (logrank) test = 15.82  on 1 df,   p=7e-05
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 7.35 (2.35-22.95); p = 0.001"

#Multivariate cox regression for RFS - ctDNA post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("G/J","Stomach"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
circ_data$ACT <- factor(circ_data$ACT, levels=c("TRUE","FALSE"))
surv_object <- Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.postNAC + PrimSite + Gender + Age.Group + ACT, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for RFS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#Multivariate cox regression for OS - ctDNA post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.postNAC <- factor(circ_data$ctDNA.postNAC, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("G/J","Stomach"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
circ_data$ACT <- factor(circ_data$ACT, levels=c("TRUE","FALSE"))
surv_object <- Surv(time = circ_data$FU.months, event = circ_data$OS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.postNAC + PrimSite + Gender + Age.Group + ACT, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for OS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#RFS by ctDNA post-NAT & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      6     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5   9.63    6.21      NA
ctDNA.Stage.II.TNM=3  5      4   7.36    2.53      NA
ctDNA.Stage.II.TNM=4  3      3   3.55    1.35      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA post-NAT & ypTN", ylab= "Disease-Free Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     25       0    1.000  0.0000        1.000        1.000
   24     13       6    0.733  0.0944        0.497        0.872

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000         1.00        1.000
   24      1       5    0.208   0.179         0.01        0.586

                ctDNA.Stage.II.TNM=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  1.9291    6.8836   0.6303 3.061  0.00221 ** 
ctDNA.Stage.II.TNMctDNA(-) & T4     2.2440    9.4313   0.6932 3.237  0.00121 ** 
ctDNA.Stage.II.TNMctDNA(+) & T4     3.2728   26.3857   0.8116 4.032 5.52e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3     6.884     0.1453     2.001     23.68
ctDNA.Stage.II.TNMctDNA(-) & T4        9.431     0.1060     2.424     36.70
ctDNA.Stage.II.TNMctDNA(+) & T4       26.386     0.0379     5.376    129.49

Concordance= 0.775  (se = 0.043 )
Likelihood ratio test= 20.62  on 3 df,   p=1e-04
Wald test            = 19.79  on 3 df,   p=2e-04
Score (logrank) test = 29.52  on 3 df,   p=2e-06
#Repeat analysis to compare ctDNA post-NAT (+) T1-T3 vs T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      6     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5   9.63    6.21      NA
ctDNA.Stage.II.TNM=3  5      4   7.36    2.53      NA
ctDNA.Stage.II.TNM=4  3      3   3.55    1.35      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                       coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.3437    3.8331   0.7683  1.749  0.08031 . 
ctDNA.Stage.II.TNM1 -1.9291    0.1453   0.6303 -3.061  0.00221 **
ctDNA.Stage.II.TNM3  0.3149    1.3701   0.6866  0.459  0.64652   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4    3.8331     0.2609   0.85028   17.2799
ctDNA.Stage.II.TNM1    0.1453     6.8836   0.04224    0.4997
ctDNA.Stage.II.TNM3    1.3701     0.7299   0.35669    5.2629

Concordance= 0.775  (se = 0.043 )
Likelihood ratio test= 20.62  on 3 df,   p=1e-04
Wald test            = 19.79  on 3 df,   p=2e-04
Score (logrank) test = 29.52  on 3 df,   p=2e-06

#OS by ctDNA post-NAT & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5  16.66   11.66      NA
ctDNA.Stage.II.TNM=3  5      3   8.31    3.58      NA
ctDNA.Stage.II.TNM=4  3      3  19.09    2.40      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA post-NAT & ypTN", ylab= "Overall Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     25       0        1       0            1            1
   24     16       0        1       0           NA           NA

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000       1.0000        1.000
   24      2       4    0.333   0.192       0.0461        0.676

                ctDNA.Stage.II.TNM=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.7833   16.1727   0.8451 3.293 0.000990 ***
ctDNA.Stage.II.TNMctDNA(-) & T4     3.6483   38.4083   1.0196 3.578 0.000346 ***
ctDNA.Stage.II.TNMctDNA(+) & T4     3.6058   36.8115   0.9977 3.614 0.000302 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3     16.17    0.06183     3.086     84.75
ctDNA.Stage.II.TNMctDNA(-) & T4        38.41    0.02604     5.207    283.33
ctDNA.Stage.II.TNMctDNA(+) & T4        36.81    0.02717     5.208    260.17

Concordance= 0.863  (se = 0.035 )
Likelihood ratio test= 24.39  on 3 df,   p=2e-05
Wald test            = 16.23  on 3 df,   p=0.001
Score (logrank) test = 30.45  on 3 df,   p=1e-06
#Repeat analysis to compare ctDNA post-NAT (+) T1-T3 vs T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.postNAC == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 25      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  8      5  16.66   11.66      NA
ctDNA.Stage.II.TNM=3  5      3   8.31    3.58      NA
ctDNA.Stage.II.TNM=4  3      3  19.09    2.40      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)      z Pr(>|z|)    
ctDNA.Stage.II.TNM4  0.82248   2.27615  0.79900  1.029  0.30329    
ctDNA.Stage.II.TNM1 -2.78333   0.06183  0.84513 -3.293  0.00099 ***
ctDNA.Stage.II.TNM3  0.86495   2.37489  0.80811  1.070  0.28447    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   2.27615     0.4393    0.4754    10.897
ctDNA.Stage.II.TNM1   0.06183    16.1727    0.0118     0.324
ctDNA.Stage.II.TNM3   2.37489     0.4211    0.4873    11.575

Concordance= 0.863  (se = 0.035 )
Likelihood ratio test= 24.39  on 3 df,   p=2e-05
Wald test            = 16.23  on 3 df,   p=0.001
Score (logrank) test = 30.45  on 3 df,   p=1e-06

#RFS by ctDNA post-NAT & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1     NA    3.55      NA
ctDNA.Stage.II.TNM=3 14      8   18.2   11.40      NA
ctDNA.Stage.II.TNM=4  8      7    7.0    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA post-NAT & ypN", ylab= "Disease-Free Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000  0.0000        1.000        1.000
   24     12       2    0.875  0.0827        0.586        0.967

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      3       0    1.000   0.000       1.0000        1.000
   24      1       1    0.667   0.272       0.0541        0.945

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     14       0    1.000    0.00       1.0000        1.000
   24      1       8    0.188    0.16       0.0107        0.539

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0  1.8009    6.0550   1.2294 1.465  0.14295    
ctDNA.Stage.II.TNMctDNA(-) & ypN+  2.3395   10.3756   0.8452 2.768  0.00564 ** 
ctDNA.Stage.II.TNMctDNA(+) & ypN+  3.7725   43.4875   0.9323 4.046  5.2e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0     6.055    0.16515    0.5441     67.38
ctDNA.Stage.II.TNMctDNA(-) & ypN+    10.376    0.09638    1.9794     54.39
ctDNA.Stage.II.TNMctDNA(+) & ypN+    43.488    0.02300    6.9948    270.37

Concordance= 0.773  (se = 0.058 )
Likelihood ratio test= 23.01  on 3 df,   p=4e-05
Wald test            = 17.09  on 3 df,   p=7e-04
Score (logrank) test = 26.38  on 3 df,   p=8e-06
#Repeat analysis to compare ctDNA post-NAT (-) vs (+) in ypN+
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1     NA    3.55      NA
ctDNA.Stage.II.TNM=3 14      8   18.2   11.40      NA
ctDNA.Stage.II.TNM=4  8      7    7.0    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("3","4","1","2"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 18 

                        coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.43302   4.19133  0.57130  2.508  0.01213 * 
ctDNA.Stage.II.TNM1 -2.33945   0.09638  0.84525 -2.768  0.00564 **
ctDNA.Stage.II.TNM2 -0.53857   0.58358  1.08425 -0.497  0.61939   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   4.19133     0.2386   1.36791   12.8424
ctDNA.Stage.II.TNM1   0.09638    10.3756   0.01839    0.5052
ctDNA.Stage.II.TNM2   0.58358     1.7136   0.06969    4.8867

Concordance= 0.773  (se = 0.058 )
Likelihood ratio test= 23.01  on 3 df,   p=4e-05
Wald test            = 17.09  on 3 df,   p=7e-04
Score (logrank) test = 26.38  on 3 df,   p=8e-06

#OS by ctDNA post-NAT & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 16      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  3      1   19.1   19.09      NA
ctDNA.Stage.II.TNM=3 14      3     NA   24.25      NA
ctDNA.Stage.II.TNM=4  8      7   14.4    8.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA post-NAT & ypN", ylab= "Overall Survival", xlab="Time from Surgery (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000  0.0000        1.000        1.000
   24     13       1    0.938  0.0605        0.632        0.991

                ctDNA.Stage.II.TNM=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      3       0      1.0   0.000      1.00000         1.00
   24      1       1      0.5   0.354      0.00598         0.91

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     14       0    1.000  0.0000        1.000        1.000
   24      3       2    0.857  0.0935        0.539        0.962

                ctDNA.Stage.II.TNM=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000      1.00000        1.000
   24      1       6    0.146   0.135      0.00726        0.471
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0  1.4824    4.4036   1.2274 1.208 0.227138    
ctDNA.Stage.II.TNMctDNA(-) & ypN+  1.4115    4.1022   0.9495 1.487 0.137123    
ctDNA.Stage.II.TNMctDNA(+) & ypN+  3.1167   22.5721   0.8727 3.571 0.000355 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0     4.404     0.2271    0.3972     48.82
ctDNA.Stage.II.TNMctDNA(-) & ypN+     4.102     0.2438    0.6380     26.38
ctDNA.Stage.II.TNMctDNA(+) & ypN+    22.572     0.0443    4.0804    124.87

Concordance= 0.765  (se = 0.076 )
Likelihood ratio test= 16.79  on 3 df,   p=8e-04
Wald test            = 15.08  on 3 df,   p=0.002
Score (logrank) test = 23.63  on 3 df,   p=3e-05
#Repeat analysis to compare ctDNA post-NAT (+) ypN0 vs ypN+
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.postNAC!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.postNAC == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.postNAC == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 41, number of events= 13 

                        coef exp(coef) se(coef)      z Pr(>|z|)
ctDNA.Stage.II.TNM4  1.63430   5.12585  1.11292  1.468    0.142
ctDNA.Stage.II.TNM1 -1.48242   0.22709  1.22741 -1.208    0.227
ctDNA.Stage.II.TNM3 -0.07091   0.93155  1.17530 -0.060    0.952

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4    5.1259     0.1951   0.57869    45.403
ctDNA.Stage.II.TNM1    0.2271     4.4036   0.02048     2.517
ctDNA.Stage.II.TNM3    0.9315     1.0735   0.09306     9.325

Concordance= 0.765  (se = 0.076 )
Likelihood ratio test= 16.79  on 3 df,   p=8e-04
Wald test            = 15.08  on 3 df,   p=0.002
Score (logrank) test = 23.63  on 3 df,   p=3e-05

#DFS by ctDNA Clearance post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 10      7   7.79    2.56      NA
ctDNA.C2D1.Clearance=TRUE  17      6     NA   18.20      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="RFS - ctDNA clearance post-NAT", ylab= "Recurrence-Free Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    24.00000      1.00000      7.00000      0.15000      0.13555      0.00802      0.47435 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
      24.000        6.000        6.000        0.613        0.128        0.324        0.809 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 27, number of events= 13 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.C2D1.ClearanceFALSE 1.4237    4.1523   0.5823 2.445   0.0145 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     4.152     0.2408     1.326        13

Concordance= 0.668  (se = 0.064 )
Likelihood ratio test= 5.82  on 1 df,   p=0.02
Wald test            = 5.98  on 1 df,   p=0.01
Score (logrank) test = 6.85  on 1 df,   p=0.009
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 4.15 (1.33-13); p = 0.014"

#OS by ctDNA Clearance post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.C2D1.Clearance <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C2D1.Clearance = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "TRUE",
    ctDNA.Base == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "FALSE",
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.C2D1.Clearance),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.C2D1.Clearance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.C2D1.Clearance, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.C2D1.Clearance=FALSE 10      7   18.9    11.7      NA
ctDNA.C2D1.Clearance=TRUE  17      2     NA      NA      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C2D1.Clearance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("red","blue"), title="OS - ctDNA clearance post-NAT", ylab= "Overall Survival", xlab="Months from Surgery", legend.labs=c("No Clearance", "Clearance"), legend.title="")

summary(KM_curve, times= c(24))
Call: survfit(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C2D1.Clearance=FALSE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       2.0000       6.0000       0.2571       0.1560       0.0384       0.5679 

                ctDNA.C2D1.Clearance=TRUE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     24.0000       6.0000       2.0000       0.8824       0.0781       0.6060       0.9692 
circ_data$ctDNA.C2D1.Clearance <- factor(circ_data$ctDNA.C2D1.Clearance, levels=c("TRUE","FALSE"))
cox_fit <- coxph(surv_object ~ ctDNA.C2D1.Clearance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C2D1.Clearance, data = circ_data)

  n= 27, number of events= 9 

                            coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.C2D1.ClearanceFALSE 2.0846    8.0411   0.8039 2.593  0.00951 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C2D1.ClearanceFALSE     8.041     0.1244     1.664     38.87

Concordance= 0.709  (se = 0.089 )
Likelihood ratio test= 8.55  on 1 df,   p=0.003
Wald test            = 6.72  on 1 df,   p=0.01
Score (logrank) test = 9.48  on 1 df,   p=0.002
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 8.04 (1.66-38.87); p = 0.01"

#Association of ctDNA Dynamics post-NAT and Response

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      1     NA   18.20      NA
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-", "ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRG <- factor(circ_data$TRG, levels = c("TRG1/2/3", "TRG4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRG)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning in stats::chisq.test(x, y, ...) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test

data:  contingency_table
X-squared = 11.378, df = 2, p-value = 0.003383
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.002557
alternative hypothesis: two.sided
print(contingency_table)
             
              TRG1/2/3 TRG4/5
  ctDNA +/-/-        4      0
  ctDNA +/+/-        6      4
  ctDNA +/+/+        0      7
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2

# Swapping x and y in ggplot function to make bar plot vertical
ggplot(table_df, aes(y = Var1, x = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(x = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA Dymamics post-NAT", y = "ctDNA", x = "Patients (%)", fill = "Path Response") +
  scale_x_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("TRG1/2/3" = "lightblue3", "TRG4/5" = "red")) + # define custom colors
  theme(axis.text.y = element_text(angle = 0, hjust = 1.5, size = 14), # increase y-axis text size
        axis.text.x = element_text(size = 14, color = "black"), # increase x-axis text size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Recurrence label size


#Calculating p-value with Fisher exact test for the ctDNA +/+/+ vs ctDNA +/+/-
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

#Vertical Fisher plot for ctDNA clearance post-NAT and Rec Status
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="",]
circ_data <- circ_data[circ_data$ctDNA.Dynamics!="ctDNA +/-/-",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

   40 observations deleted due to missingness 
                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/+/-", "ctDNA +/+/+"))
circ_data$TRG <- factor(circ_data$TRG, levels = c("TRG1/2/3", "TRG4/5"))
contingency_table <- table(circ_data$ctDNA.Dynamics, circ_data$TRG)
fisher_exact_test <- fisher.test(contingency_table)
chi_square_test <- chisq.test(contingency_table)
Warning in stats::chisq.test(x, y, ...) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 4.1295, df = 1, p-value = 0.04214
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.0345
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 1.176016      Inf
sample estimates:
odds ratio 
       Inf 
print(contingency_table)
             
              TRG1/2/3 TRG4/5
  ctDNA +/+/-        6      4
  ctDNA +/+/+        0      7

#DFS by ctDNA Dynamics post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.Dynamics),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      1     NA   18.20      NA
ctDNA.Dynamics=ctDNA +/+/- 10      5  14.55    7.36      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   6.21    2.04      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA Dynamics post-NAT", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=ctDNA +/-/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      5       0    1.000   0.000       1.0000        1.000
   24      2       1    0.667   0.272       0.0541        0.945

                ctDNA.Dynamics=ctDNA +/+/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0     1.00   0.000        1.000        1.000
   24      2       5     0.48   0.164        0.161        0.745

                ctDNA.Dynamics=ctDNA +/+/+ 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            7            0            1            0            1            1 
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
cox_fit <- coxph(surv_object ~ ctDNA.Dynamics, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

  n= 22, number of events= 12 

                            coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.DynamicsctDNA +/+/-  1.343     3.831    1.100 1.221   0.2219  
ctDNA.DynamicsctDNA +/+/+  2.921    18.568    1.157 2.526   0.0116 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.DynamicsctDNA +/+/-     3.831    0.26100    0.4439     33.07
ctDNA.DynamicsctDNA +/+/+    18.568    0.05386    1.9237    179.22

Concordance= 0.756  (se = 0.053 )
Likelihood ratio test= 10.01  on 2 df,   p=0.007
Wald test            = 8.49  on 2 df,   p=0.01
Score (logrank) test = 11.47  on 2 df,   p=0.003

#OS by ctDNA Dynamics post-NAT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.Dynamics),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                            n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=ctDNA +/-/-  5      0     NA      NA      NA
ctDNA.Dynamics=ctDNA +/+/- 10      2     NA      NA      NA
ctDNA.Dynamics=ctDNA +/+/+  7      6   14.4    8.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA Dynamics post-NAT", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=ctDNA +/-/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      5       0        1       0            1            1
   24      2       0        1       0           NA           NA

                ctDNA.Dynamics=ctDNA +/+/- 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0      1.0   0.000        1.000        1.000
   24      2       2      0.8   0.126        0.409        0.946

                ctDNA.Dynamics=ctDNA +/+/+ 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      7       0    1.000   0.000      1.00000        1.000
   24      1       5    0.171   0.156      0.00794        0.526
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
cox_fit <- coxphf(surv_object ~ ctDNA.Dynamics, data=circ_data)
summary(cox_fit)
coxphf(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

Model fitted by Penalized ML
Confidence intervals and p-values by Profile Likelihood 

                              coef se(coef) exp(coef) lower 0.95 upper 0.95     Chisq           p
ctDNA.DynamicsctDNA +/+/- 1.178268 1.696304  3.248742  0.2627946    448.914 0.7281482 0.393484095
ctDNA.DynamicsctDNA +/+/+ 2.776185 1.609915 16.057642  1.8668569   2102.174 7.2774206 0.006982673

Likelihood ratio test=8.847995 on 2 df, p=0.01198622, n=22
Wald test = 5.979249 on 2 df, p = 0.05030632

Covariance-Matrix:
                          ctDNA.DynamicsctDNA +/+/- ctDNA.DynamicsctDNA +/+/+
ctDNA.DynamicsctDNA +/+/-                  2.877449                  2.403504
ctDNA.DynamicsctDNA +/+/+                  2.403504                  2.591825

#Levels of Baseline MTM/mL in ctDNA Dynamics post-NAT categories

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.Base!="",]
circ_data <- as.data.frame(circ_data)

circ_data$ctDNA.Dynamics <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Dynamics = case_when(
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "NEGATIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/-/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "NEGATIVE" ~ "ctDNA +/+/-",
    ctDNA.Base == "POSITIVE" & ctDNA.C2D1 == "POSITIVE" & ctDNA.postNAC == "POSITIVE" ~ "ctDNA +/+/+"
  ))

# Transform ctDNA.Base.MTM with log10
circ_data <- subset(circ_data, !is.na(ctDNA.Dynamics))
circ_data$ctDNA.Base.MTM <- as.numeric(as.character(circ_data$ctDNA.Base.MTM))
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("ctDNA +/-/-","ctDNA +/+/-", "ctDNA +/+/+"))
median_Base_MTM <- aggregate(ctDNA.Base.MTM ~ ctDNA.Dynamics, data = circ_data, FUN = median)
print(median_Base_MTM)

# Create violin plot with log10 scale on y-axis
ggplot(circ_data, aes(x=ctDNA.Dynamics, y=ctDNA.Base.MTM, fill=ctDNA.Dynamics)) +
  geom_violin(trim=FALSE) +
  scale_fill_manual(values=c("ctDNA +/-/-"="lightblue", "ctDNA +/+/-"="lightgreen", "ctDNA +/+/+"="salmon")) +
  geom_boxplot(width=0.1, fill="white", colour="black", alpha=0.5) +
  scale_y_log10(breaks=c(0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000)) +
  labs(title="Baseline MTM/mL | Dynamics post-NAT", x="Dynamics post-NAT", y="Baseline MTM/mL") +
  theme_minimal() +
  theme(legend.position="none")

m3_1v2 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/-/-", "ctDNA +/+/-"), ],
                      na.rm = TRUE)
Warning in wilcox.test.default(x = DATA[[1L]], y = DATA[[2L]], ...) :
  cannot compute exact p-value with ties
print(m3_1v2)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 26, p-value = 0.9511
alternative hypothesis: true location shift is not equal to 0
m3_1v3 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/-/-", "ctDNA +/+/+"), ],
                      na.rm = TRUE)
print(m3_1v3)

    Wilcoxon rank sum exact test

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 7, p-value = 0.1061
alternative hypothesis: true location shift is not equal to 0
m3_2v3 <- wilcox.test(ctDNA.Base.MTM ~ ctDNA.Dynamics,
                      data = circ_data[circ_data$ctDNA.Dynamics %in% c("ctDNA +/+/-", "ctDNA +/+/+"), ],
                      na.rm = TRUE)
Warning in wilcox.test.default(x = DATA[[1L]], y = DATA[[2L]], ...) :
  cannot compute exact p-value with ties
print(m3_2v3)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.Base.MTM by ctDNA.Dynamics
W = 2, p-value = 0.001506
alternative hypothesis: true location shift is not equal to 0

#DFS by ctDNA post-NAT & TRG combination

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.postNAC == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      5     NA      NA      NA
ctDNA.pCR=2  6      5     11    2.53      NA
ctDNA.pCR=3 10      8      7    2.56      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA post-NAT/TRG", ylab= "Recurrence-Free Survival", xlab="Months from surgery", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000   0.000        1.000        1.000
   24     13       5    0.767   0.092        0.526        0.897

                ctDNA.pCR=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 

                ctDNA.pCR=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0    1.000   0.000      1.00000        1.000
   24      1       8    0.125   0.115      0.00702        0.418
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 39, number of events= 18 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  2.1228    8.3545   0.6529 3.251  0.00115 ** 
ctDNA.pCRTRG4/5 ctDNA (+)  2.3546   10.5336   0.5969 3.945 7.99e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     8.355    0.11970     2.323     30.04
ctDNA.pCRTRG4/5 ctDNA (+)    10.534    0.09493     3.270     33.94

Concordance= 0.765  (se = 0.044 )
Likelihood ratio test= 19.53  on 2 df,   p=6e-05
Wald test            = 17.01  on 2 df,   p=2e-04
Score (logrank) test = 23.41  on 2 df,   p=8e-06

#OS by ctDNA post-NAT & TRG combination

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.postNAC == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.postNAC == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      2     NA      NA      NA
ctDNA.pCR=2  6      3   8.31    3.58      NA
ctDNA.pCR=3 10      8  18.89   11.66      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA post-NAT/TRG", ylab= "Overall Survival", xlab="Months from surgery", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0        1       0            1            1
   24     15       0        1       0           NA           NA

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      6       0      1.0   0.000        1.000        1.000
   24      1       3      0.5   0.204        0.111        0.804

                ctDNA.pCR=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     10       0    1.000    0.00       1.0000        1.000
   24      2       7    0.225    0.14       0.0342        0.517
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 39, number of events= 13 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  2.7343   15.3983   0.9416 2.904 0.003685 ** 
ctDNA.pCRTRG4/5 ctDNA (+)  2.8771   17.7633   0.8035 3.581 0.000343 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     15.40    0.06494     2.432     97.49
ctDNA.pCRTRG4/5 ctDNA (+)     17.76    0.05630     3.678     85.80

Concordance= 0.811  (se = 0.04 )
Likelihood ratio test= 19.74  on 2 df,   p=5e-05
Wald test            = 13.12  on 2 df,   p=0.001
Score (logrank) test = 22.59  on 2 df,   p=1e-05

#DFS by ctDNA at the MRD Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 40     14     NA   23.32      NA
ctDNA.MRD=POSITIVE  7      7   3.57    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="RFS - ctDNA MRD window | All pts", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     40       0    1.000  0.0000        1.000        1.000
   24     18      13    0.628  0.0836        0.442        0.766

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            7            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 47, number of events= 21 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.5604   12.9415   0.5704 4.489 7.17e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     12.94    0.07727     4.231     39.59

Concordance= 0.666  (se = 0.047 )
Likelihood ratio test= 17.26  on 1 df,   p=3e-05
Wald test            = 20.15  on 1 df,   p=7e-06
Score (logrank) test = 31.36  on 1 df,   p=2e-08
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 12.94 (4.23-39.59); p = 0"

#OS by ctDNA at the MRD Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 40      6     NA      NA      NA
ctDNA.MRD=POSITIVE 10      8   8.59    5.31      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","red"), title="OS - ctDNA MRD window | All pts", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     40       0    1.000  0.0000        1.000        1.000
   24     23       5    0.849  0.0632        0.671        0.935

                ctDNA.MRD=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0           10            0            1            0            1            1 
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 50, number of events= 14 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.MRDPOSITIVE  2.6769   14.5406   0.5942 4.505 6.64e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     14.54    0.06877     4.537      46.6

Concordance= 0.771  (se = 0.055 )
Likelihood ratio test= 19.56  on 1 df,   p=1e-05
Wald test            = 20.29  on 1 df,   p=7e-06
Score (logrank) test = 33.05  on 1 df,   p=9e-09
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 14.54 (4.54-46.6); p = 0"

#RFS by ctDNA at the MRD Window & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      8     NA      NA      NA
ctDNA.Stage.II.TNM=2  4      4   5.10    3.21      NA
ctDNA.Stage.II.TNM=3  9      6  19.34   11.55      NA
ctDNA.Stage.II.TNM=4  3      3   3.51    1.70      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA MRD & ypTN", ylab= "Disease-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   24     15       8    0.698   0.091        0.481        0.838

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0      1.0   0.000       1.0000        1.000
   24      3       5      0.4   0.174       0.0981        0.697

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.6818   14.6110   0.6876 3.900 9.62e-05 ***
ctDNA.Stage.II.TNMctDNA(-) & T4     1.0893    2.9722   0.5407 2.015   0.0439 *  
ctDNA.Stage.II.TNMctDNA(+) & T4     3.4934   32.8977   0.8353 4.182 2.89e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3    14.611    0.06844     3.796    56.233
ctDNA.Stage.II.TNMctDNA(-) & T4        2.972    0.33645     1.030     8.576
ctDNA.Stage.II.TNMctDNA(+) & T4       32.898    0.03040     6.399   169.126

Concordance= 0.731  (se = 0.051 )
Likelihood ratio test= 21.92  on 3 df,   p=7e-05
Wald test            = 22.7  on 3 df,   p=5e-05
Score (logrank) test = 37.96  on 3 df,   p=3e-08
#Repeat analysis to compare ctDNA MRD (-) vs (+) in T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      8     NA      NA      NA
ctDNA.Stage.II.TNM=2  4      4   5.10    3.21      NA
ctDNA.Stage.II.TNM=3  9      6  19.34   11.55      NA
ctDNA.Stage.II.TNM=4  3      3   3.51    1.70      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA MRD & ypTN", ylab= "Disease-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   24     15       8    0.698   0.091        0.481        0.838

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0      1.0   0.000       1.0000        1.000
   24      3       5      0.4   0.174       0.0981        0.697

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                        coef exp(coef) se(coef)      z Pr(>|z|)    
ctDNA.Stage.II.TNM4  0.81163   2.25158  0.80842  1.004   0.3154    
ctDNA.Stage.II.TNM1 -2.68177   0.06844  0.68763 -3.900 9.62e-05 ***
ctDNA.Stage.II.TNM3 -1.59246   0.20342  0.71596 -2.224   0.0261 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   2.25158     0.4441   0.46170   10.9804
ctDNA.Stage.II.TNM1   0.06844    14.6110   0.01778    0.2634
ctDNA.Stage.II.TNM3   0.20342     4.9158   0.05000    0.8276

Concordance= 0.731  (se = 0.051 )
Likelihood ratio test= 21.92  on 3 df,   p=7e-05
Wald test            = 22.7  on 3 df,   p=5e-05
Score (logrank) test = 37.96  on 3 df,   p=3e-08

#OS by ctDNA at the MRD Window & ypT

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      3     NA      NA      NA
ctDNA.Stage.II.TNM=2  5      3  21.48    8.66      NA
ctDNA.Stage.II.TNM=3  9      3  49.70   49.70      NA
ctDNA.Stage.II.TNM=4  5      5   5.31    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypTN", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000        1.000        1.000
   24     18       3    0.875  0.0681        0.658        0.959

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000        1.000        1.000
   24      5       2    0.762   0.148        0.332        0.935

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & T1-T3  2.5315   12.5725   0.8498 2.979  0.00289 ** 
ctDNA.Stage.II.TNMctDNA(-) & T4     1.2740    3.5751   0.8169 1.560  0.11886    
ctDNA.Stage.II.TNMctDNA(+) & T4     4.5082   90.7580   0.9252 4.873  1.1e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & T1-T3    12.573    0.07954     2.377     66.49
ctDNA.Stage.II.TNMctDNA(-) & T4        3.575    0.27971     0.721     17.73
ctDNA.Stage.II.TNMctDNA(+) & T4       90.758    0.01102    14.804    556.40

Concordance= 0.829  (se = 0.056 )
Likelihood ratio test= 27.86  on 3 df,   p=4e-06
Wald test            = 24.63  on 3 df,   p=2e-05
Score (logrank) test = 59.15  on 3 df,   p=9e-13
#Repeat analysis to compare ctDNA post-NAT (-) vs (+) in T4
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T1-T3" ~ 1,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T1-T3" ~ 2,
    ctDNA.MRD == "NEGATIVE" & pT.Stage == "T4" ~ 3,
    ctDNA.MRD == "POSITIVE" & pT.Stage == "T4" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 31      3     NA      NA      NA
ctDNA.Stage.II.TNM=2  5      3  21.48    8.66      NA
ctDNA.Stage.II.TNM=3  9      3  49.70   49.70      NA
ctDNA.Stage.II.TNM=4  5      5   5.31    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypTN", ylab= "Overall Survival Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & T1-T3", "ctDNA(+) & T1-T3", "ctDNA(-) & T4", "ctDNA(+) & T4"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000        1.000        1.000
   24     18       3    0.875  0.0681        0.658        0.959

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000        1.000        1.000
   24      5       2    0.762   0.148        0.332        0.935

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("2","4","1","3"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                        coef exp(coef) se(coef)      z Pr(>|z|)   
ctDNA.Stage.II.TNM4  1.97669   7.21877  0.84482  2.340  0.01930 * 
ctDNA.Stage.II.TNM1 -2.53151   0.07954  0.84981 -2.979  0.00289 **
ctDNA.Stage.II.TNM3 -1.25752   0.28436  0.84413 -1.490  0.13629   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNM4   7.21877     0.1385   1.37833   37.8071
ctDNA.Stage.II.TNM1   0.07954    12.5725   0.01504    0.4207
ctDNA.Stage.II.TNM3   0.28436     3.5167   0.05437    1.4873

Concordance= 0.829  (se = 0.056 )
Likelihood ratio test= 27.86  on 3 df,   p=4e-06
Wald test            = 24.63  on 3 df,   p=2e-05
Score (logrank) test = 59.15  on 3 df,   p=9e-13

#RFS by ctDNA at the MRD Window & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 24      5     NA      NA      NA
ctDNA.Stage.II.TNM=2  1      1   1.70      NA      NA
ctDNA.Stage.II.TNM=3 16      9  15.20   10.34      NA
ctDNA.Stage.II.TNM=4  6      6   3.97    3.51      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA MRD & ypN", ylab= "Disease-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     24       0    1.000  0.0000        1.000         1.00
   24     17       4    0.823  0.0807        0.593         0.93

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            1            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000   0.000      1.00000        1.000
   24      1       9    0.148   0.132      0.00842        0.466

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 47, number of events= 21 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0   5.9532  384.9884   1.5428 3.859 0.000114 ***
ctDNA.Stage.II.TNMctDNA(-) & ypN+   2.0297    7.6117   0.6062 3.348 0.000814 ***
ctDNA.Stage.II.TNMctDNA(+) & ypN+   3.6876   39.9503   0.7639 4.827 1.38e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0   384.988   0.002597    18.715   7919.53
ctDNA.Stage.II.TNMctDNA(-) & ypN+     7.612   0.131377     2.320     24.97
ctDNA.Stage.II.TNMctDNA(+) & ypN+    39.950   0.025031     8.939    178.56

Concordance= 0.792  (se = 0.048 )
Likelihood ratio test= 31.15  on 3 df,   p=8e-07
Wald test            = 27.95  on 3 df,   p=4e-06
Score (logrank) test = 54.44  on 3 df,   p=9e-12

#OS by ctDNA at the MRD Window & ypN

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.Stage.II.Risk <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.Stage.II.TNM = case_when(
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N0" ~ 1,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N0" ~ 2,
    ctDNA.MRD == "NEGATIVE" & ypNStatus == "N1-N3" ~ 3,
    ctDNA.MRD == "POSITIVE" & ypNStatus == "N1-N3" ~ 4
  ))

circ_data <- circ_data[circ_data$ctDNA.Stage.II.TNM!="",]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.Stage.II.TNM, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.Stage.II.TNM, data = circ_data)

                      n events median 0.95LCL 0.95UCL
ctDNA.Stage.II.TNM=1 24      2     NA      NA      NA
ctDNA.Stage.II.TNM=2  2      2   4.46    0.38      NA
ctDNA.Stage.II.TNM=3 16      4     NA   21.25      NA
ctDNA.Stage.II.TNM=4  8      6   9.46    5.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.Stage.II.TNM, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="OS - ctDNA MRD & ypN", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Stage.II.TNM=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     24       0    1.000  0.0000        1.000        1.000
   24     20       1    0.957  0.0425        0.729        0.994

                ctDNA.Stage.II.TNM=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            2            0            1            0            1            1 

                ctDNA.Stage.II.TNM=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     16       0    1.000    0.00        1.000        1.000
   24      3       4    0.565    0.19        0.165        0.835

                ctDNA.Stage.II.TNM=4 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 
circ_data$ctDNA.Stage.II.TNM <- factor(circ_data$ctDNA.Stage.II.TNM, levels=c("1","2","3","4"), labels = c("ctDNA(-) & ypN0", "ctDNA(+) & ypN0", "ctDNA(-) & ypN+", "ctDNA(+) & ypN+"))
cox_fit <- coxph(surv_object ~ ctDNA.Stage.II.TNM, data=circ_data) 
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Stage.II.TNM, data = circ_data)

  n= 50, number of events= 14 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.Stage.II.TNMctDNA(+) & ypN0   5.0035  148.9381   1.1735 4.264 2.01e-05 ***
ctDNA.Stage.II.TNMctDNA(-) & ypN+   1.8810    6.5597   0.9016 2.086    0.037 *  
ctDNA.Stage.II.TNMctDNA(+) & ypN+   3.5092   33.4225   0.8993 3.902 9.53e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.Stage.II.TNMctDNA(+) & ypN0    148.94   0.006714    14.932    1485.5
ctDNA.Stage.II.TNMctDNA(-) & ypN+      6.56   0.152445     1.120      38.4
ctDNA.Stage.II.TNMctDNA(+) & ypN+     33.42   0.029920     5.736     194.8

Concordance= 0.86  (se = 0.04 )
Likelihood ratio test= 26.4  on 3 df,   p=8e-06
Wald test            = 23  on 3 df,   p=4e-05
Score (logrank) test = 46.69  on 3 df,   p=4e-10

#DFS by ctDNA at the MRD Window & TRG combination

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.MRD == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      6     NA   39.09      NA
ctDNA.pCR=2 12      6  15.60   11.55      NA
ctDNA.pCR=3  3      3   4.36    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="RFS - ctDNA MRD/TRG", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000  0.0000        1.000        1.000
   24     12       5    0.749  0.0993        0.492        0.889

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     12       0    1.000   0.000        1.000        1.000
   24      4       6    0.417   0.157        0.131        0.686

                ctDNA.pCR=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            3            0            1            0            1            1 
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 38, number of events= 15 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  0.9323    2.5404   0.5794 1.609 0.107610    
ctDNA.pCRTRG4/5 ctDNA (+)  3.0190   20.4704   0.8850 3.411 0.000647 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)      2.54    0.39364     0.816     7.909
ctDNA.pCRTRG4/5 ctDNA (+)     20.47    0.04885     3.612   116.004

Concordance= 0.7  (se = 0.064 )
Likelihood ratio test= 10.66  on 2 df,   p=0.005
Wald test            = 11.83  on 2 df,   p=0.003
Score (logrank) test = 19.3  on 2 df,   p=6e-05

#OS by ctDNA at the MRD Window & TRG combination

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]

circ_data$ctDNA.pCR <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG1/2/3" ~ "1",
    ctDNA.MRD == "NEGATIVE" & TRG == "TRG4/5" ~ "2",
    ctDNA.MRD == "POSITIVE" & TRG == "TRG4/5" ~ "3"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 23      3     NA   49.70      NA
ctDNA.pCR=2 12      3     NA   16.09      NA
ctDNA.pCR=3  6      6   5.42    0.58      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","red"), title="OS - ctDNA MRD/TRG", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"), legend.title="")

summary(KM_curve, times= c(0,24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     23       0    1.000  0.0000        1.000        1.000
   24     13       2    0.886  0.0776        0.607        0.971

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     12       0      1.0   0.000        1.000        1.000
   24      6       3      0.7   0.145        0.329        0.892

                ctDNA.pCR=3 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            6            0            1            0            1            1 
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2","3"), labels=c("TRG1/2/3 ctDNA (-)","TRG4/5 ctDNA (-)", "TRG4/5 ctDNA (+)"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 41, number of events= 12 

                             coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRTRG4/5 ctDNA (-)  0.6450    1.9061   0.8202 0.786    0.432    
ctDNA.pCRTRG4/5 ctDNA (+)  3.1621   23.6201   0.7401 4.273 1.93e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                          exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRTRG4/5 ctDNA (-)     1.906    0.52464    0.3819     9.513
ctDNA.pCRTRG4/5 ctDNA (+)    23.620    0.04234    5.5374   100.753

Concordance= 0.812  (se = 0.065 )
Likelihood ratio test= 18.73  on 2 df,   p=9e-05
Wald test            = 21.36  on 2 df,   p=2e-05
Score (logrank) test = 38.75  on 2 df,   p=4e-09

#DFS by ctDNA at the MRD Window & ypTN Characteristics

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included == TRUE,]
circ_data$DFS.months <- circ_data$DFS.months - 3
circ_data <- circ_data[circ_data$DFS.months >= 0,]
circ_data$ctDNA.pCR <- NA

# Define new categories
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage=="T1-T3" & ypNStatus == "N0" ~ "1",
    ctDNA.MRD == "POSITIVE" | pT.Stage == "T4" | ypNStatus == "N1-N3" ~ "2"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 19      2     NA      NA      NA
ctDNA.pCR=2 30     20   11.9    8.17    39.1
surv_object <- Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data, conf.int = 0.95, conf.type = "log-log")
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, 
           break.time.by = 12, palette = c("blue", "red"), 
           title = "DFS - ctDNA MRD/Clinical Characteristics", 
           ylab = "Disease-Free Survival", xlab = "Time from Landmark Time point (Months)", 
           legend.labs = c("MRD neg, T1-T3, N0", "MRD pos or T4 or N1-N3"), 
           legend.title = "")

summary(KM_curve, times = c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     19       0    1.000   0.000        1.000        1.000
   24     14       2    0.881   0.079        0.602        0.969

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     30       0    1.000  0.0000        1.000        1.000
   24      5      19    0.268  0.0954        0.107        0.461
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2"), labels=c("MRD neg, T1-T3, N0","MRD pos or T4 or N1-N3"))
cox_fit <- coxph(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.pCR, data = circ_data)

  n= 49, number of events= 22 

                                   coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.pCRMRD pos or T4 or N1-N3  2.5366   12.6367   0.7503 3.381 0.000723 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                exp(coef) exp(-coef) lower .95 upper .95
ctDNA.pCRMRD pos or T4 or N1-N3     12.64    0.07913     2.904     54.99

Concordance= 0.723  (se = 0.036 )
Likelihood ratio test= 20.4  on 1 df,   p=6e-06
Wald test            = 11.43  on 1 df,   p=7e-04
Score (logrank) test = 18  on 1 df,   p=2e-05
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 12.64 (2.9-54.99); p = 0.001"

#OS by ctDNA at the MRD Window & ypTN Characteristics

# Clear workspace and set working directory
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included == TRUE,]
circ_data$FU.months <- circ_data$FU.months - 3
circ_data <- circ_data[circ_data$FU.months >= 0,]
circ_data$ctDNA.pCR <- NA

# Define new categories
circ_data <- circ_data %>%
  mutate(ctDNA.pCR = case_when(
    ctDNA.MRD == "NEGATIVE" & pT.Stage=="T1-T3" & ypNStatus == "N0" ~ "1",
    ctDNA.MRD == "POSITIVE" | pT.Stage == "T4" | ypNStatus == "N1-N3" ~ "2"
  ))

circ_data <- circ_data[!is.na(circ_data$ctDNA.pCR),]
survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.pCR, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.pCR, data = circ_data)

             n events median 0.95LCL 0.95UCL
ctDNA.pCR=1 19      0     NA      NA      NA
ctDNA.pCR=2 34     16   21.5    16.1      NA
surv_object <- Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.pCR, data = circ_data, conf.int = 0.95, conf.type = "log-log")
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, 
           break.time.by = 12, palette = c("blue", "red"), 
           title = "OS - ctDNA MRD/Clinical Characteristics", 
           ylab = "Overall Survival", xlab = "Time from Landmark Time point (Months)", 
           legend.labs = c("MRD neg, T1-T3, N0", "MRD pos or T4 or N1-N3"), 
           legend.title = "")

summary(KM_curve, times = c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.pCR, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.pCR=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     19       0        1       0            1            1
   24     16       0        1       0           NA           NA

                ctDNA.pCR=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     34       0    1.000   0.000        1.000        1.000
   24      8      15    0.446   0.105        0.239        0.634
circ_data$ctDNA.pCR <- factor(circ_data$ctDNA.pCR, levels=c("1","2"), labels=c("MRD neg, T1-T3, N0","MRD pos or T4 or N1-N3"))
cox_fit <- coxphf(surv_object ~ ctDNA.pCR, data=circ_data)
summary(cox_fit)
coxphf(formula = surv_object ~ ctDNA.pCR, data = circ_data)

Model fitted by Penalized ML
Confidence intervals and p-values by Profile Likelihood 

                                    coef se(coef) exp(coef) lower 0.95 upper 0.95    Chisq            p
ctDNA.pCRMRD pos or T4 or N1-N3 3.493535 1.495302  32.90204   4.363659   4215.243 18.01942 2.186631e-05

Likelihood ratio test=18.01942 on 1 df, p=2.186631e-05, n=53
Wald test = 5.458488 on 1 df, p = 0.01947349

Covariance-Matrix:
                                ctDNA.pCRMRD pos or T4 or N1-N3
ctDNA.pCRMRD pos or T4 or N1-N3                        2.235927

#Multivariate cox regression for RFS - ctDNA MRD Window

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("G/J","Stomach"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$pT.Stage <- factor(circ_data$pT.Stage, levels=c("T1-T3","T4"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
surv_object <- Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.MRD + PrimSite + Age.Group + pT.Stage + ypNStatus + TRG, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for RFS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#Multivariate cox regression for OS - ctDNA MRD Window v1

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("G/J","Stomach"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
surv_object <- Surv(time = circ_data$FU.months, event = circ_data$OS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.MRD + PrimSite + Gender + Age.Group + ypNStatus + TRG, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for OS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#Multivariate cox regression for OS - ctDNA MRD Window v2

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_datadf <- as.data.frame(circ_data)

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"), labels = c("Negative", "Positive"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels=c("G/J","Stomach"))
circ_data$Gender <- factor(circ_data$Gender, levels=c("Male","Female"))
circ_data$Age.Group <- factor(circ_data$Age.Group, levels=c("2","1"), labels = c(">70", "≤70"))
circ_data$pT.Stage <- factor(circ_data$pT.Stage, levels=c("T1-T3","T4"))
circ_data$ypNStatus <- factor(circ_data$ypNStatus, levels=c("N0","N1-N3"))
circ_data$TRG <- factor(circ_data$TRG, levels=c("TRG1/2/3","TRG4/5"))
surv_object <- Surv(time = circ_data$FU.months, event = circ_data$OS.Event) 
cox_fit <- coxph(surv_object ~ ctDNA.MRD + PrimSite + Age.Group + pT.Stage + ypNStatus + TRG, data=circ_data) 
ggforest(cox_fit, data = circ_data, main = "Multivariate Regression Model for OS", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#DFS by ctDNA at the Surveillance Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.surveillance!="",]
circ_data$DFS.months=circ_data$DFS.months-3
circ_data <- circ_data[circ_data$DFS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)~ctDNA.surveillance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event) ~ 
    ctDNA.surveillance, data = circ_data)

                             n events median 0.95LCL 0.95UCL
ctDNA.surveillance=NEGATIVE 33     10     NA   39.09      NA
ctDNA.surveillance=POSITIVE  4      4   6.27    3.21      NA
surv_object <-Surv(time = circ_data$DFS.months, event = circ_data$DFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.surveillance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="RFS - ctDNA Surveillance window | All pts", ylab= "Recurrence-Free Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.surveillance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.surveillance=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     33       0    1.000  0.0000         1.00         1.00
   24     16       9    0.679  0.0896         0.47         0.82

                ctDNA.surveillance=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            4            0            1            0            1            1 
circ_data$ctDNA.surveillance <- factor(circ_data$ctDNA.surveillance, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.surveillance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.surveillance, data = circ_data)

  n= 37, number of events= 14 

                              coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.surveillancePOSITIVE  2.7504   15.6482   0.7292 3.772 0.000162 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                           exp(coef) exp(-coef) lower .95 upper .95
ctDNA.surveillancePOSITIVE     15.65    0.06391     3.748     65.34

Concordance= 0.657  (se = 0.06 )
Likelihood ratio test= 11.52  on 1 df,   p=7e-04
Wald test            = 14.23  on 1 df,   p=2e-04
Score (logrank) test = 24.6  on 1 df,   p=7e-07
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 15.65 (3.75-65.34); p = 0"

#OS by ctDNA at the Surveillance Window - all stages

rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("PLAGAST_Clinical Data.csv")
circ_data <- circ_data[circ_data$Included==TRUE,]
circ_data <- circ_data[circ_data$ctDNA.surveillance!="",]
circ_data$FU.months=circ_data$FU.months-3
circ_data <- circ_data[circ_data$FU.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$FU.months, event = circ_data$OS.Event)~ctDNA.surveillance, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$FU.months, event = circ_data$OS.Event) ~ 
    ctDNA.surveillance, data = circ_data)

                             n events median 0.95LCL 0.95UCL
ctDNA.surveillance=NEGATIVE 33      5     NA      NA      NA
ctDNA.surveillance=POSITIVE  5      3   8.66    5.54      NA
surv_object <-Surv(time = circ_data$FU.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.surveillance, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA Surveillance window | All pts", ylab= "Overall Survival", xlab="Time from Landmark Time point (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(0, 24))
Call: survfit(formula = surv_object ~ ctDNA.surveillance, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.surveillance=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     33       0    1.000  0.0000        1.000        1.000
   24     20       3    0.886  0.0626        0.684        0.962

                ctDNA.surveillance=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            5            0            1            0            1            1 
circ_data$ctDNA.surveillance <- factor(circ_data$ctDNA.surveillance, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.surveillance, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.surveillance, data = circ_data)

  n= 38, number of events= 8 

                              coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.surveillancePOSITIVE  2.7378   15.4530   0.9239 2.963  0.00304 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                           exp(coef) exp(-coef) lower .95 upper .95
ctDNA.surveillancePOSITIVE     15.45    0.06471     2.527      94.5

Concordance= 0.727  (se = 0.088 )
Likelihood ratio test= 8.06  on 1 df,   p=0.005
Wald test            = 8.78  on 1 df,   p=0.003
Score (logrank) test = 15.41  on 1 df,   p=9e-05
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 15.45 (2.53-94.5); p = 0.003"
LS0tCnRpdGxlOiAiQUdFTyBQTEFHQVNUX0NsaW5pY2FsIEZpbmFsIGFuYWx5c2lzIDA2MTIyMDI0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmxpYnJhcnkoc3dpbXBsb3QpCmxpYnJhcnkoY294cGhmKQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3RhYmxlKQpsaWJyYXJ5KHJlYWRyKSAKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkoZHBseXIpIApsaWJyYXJ5KHN1cnZpdmFsKSAKbGlicmFyeShzdXJ2bWluZXIpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGNveHBoZikKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ3RzdW1tYXJ5KQpsaWJyYXJ5KGZsZXh0YWJsZSkKbGlicmFyeShwYXJhbWV0ZXJzKQpsaWJyYXJ5KGNhcikKbGlicmFyeShDb21wbGV4SGVhdG1hcCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHN1cnZpdmFsKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkob3Blbnhsc3gpCmxpYnJhcnkod3JpdGV4bCkKbGlicmFyeShybXMpCmxpYnJhcnkocFJPQykKbGlicmFyeShEVCkKCiNjdEROQSBEZXRlY3Rpb24gcmF0ZSBieSBTdGFnZSBhbmQgV2luZG93CmBgYHtyfQojQmFzZWxpbmUKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5CYXNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQmFzZSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJIiwiSUkiLCJJSUkiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLkJhc2UgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5CYXNlID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuQmFzZSwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49bGVuZ3RoKQpjb21iaW5lZF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkR3JvdXAuMSwKICBUb3RhbF9Db3VudCA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSR4LAogIFBvc2l0aXZlX0NvdW50ID0gcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHgsCiAgUmF0ZSA9IChwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCAvIHRvdGFsX2NvdW50c19ieV9zdGFnZSR4KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKKQpjb21iaW5lZF9kYXRhJFJhdGUgPC0gc3ByaW50ZigiJS4yZiUlIiwgY29tYmluZWRfZGF0YSRSYXRlKQpvdmVyYWxsX3RvdGFsX2NvdW50IDwtIG5yb3coY2lyY19kYXRhKQpvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IDwtIG5yb3coY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI0MyRDEKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5DMkQxIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzJEMSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJIiwiSUkiLCJJSUkiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLkMyRDEgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5DMkQxID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuQzJEMSwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49bGVuZ3RoKQpjb21iaW5lZF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkR3JvdXAuMSwKICBUb3RhbF9Db3VudCA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSR4LAogIFBvc2l0aXZlX0NvdW50ID0gcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHgsCiAgUmF0ZSA9IChwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCAvIHRvdGFsX2NvdW50c19ieV9zdGFnZSR4KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKKQpjb21iaW5lZF9kYXRhJFJhdGUgPC0gc3ByaW50ZigiJS4yZiUlIiwgY29tYmluZWRfZGF0YSRSYXRlKQpvdmVyYWxsX3RvdGFsX2NvdW50IDwtIG5yb3coY2lyY19kYXRhKQpvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IDwtIG5yb3coY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5DMkQxID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI3Bvc3QtTkFDIFdpbmRvdwpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEucG9zdE5BQyAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojTVJEIFdpbmRvdwpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJIiwiSUkiLCJJSUkiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLk1SRCAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1zdW0pCnRvdGFsX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLk1SRCwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49bGVuZ3RoKQpjb21iaW5lZF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkR3JvdXAuMSwKICBUb3RhbF9Db3VudCA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSR4LAogIFBvc2l0aXZlX0NvdW50ID0gcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHgsCiAgUmF0ZSA9IChwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCAvIHRvdGFsX2NvdW50c19ieV9zdGFnZSR4KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKKQpjb21iaW5lZF9kYXRhJFJhdGUgPC0gc3ByaW50ZigiJS4yZiUlIiwgY29tYmluZWRfZGF0YSRSYXRlKQpvdmVyYWxsX3RvdGFsX2NvdW50IDwtIG5yb3coY2lyY19kYXRhKQpvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IDwtIG5yb3coY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojT24tdHJlYXRtZW50CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkY3RETkEub25BQ1QgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5vbkFDVCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJIiwiSUkiLCJJSUkiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLm9uQUNUICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEub25BQ1QgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5vbkFDVCwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49bGVuZ3RoKQpjb21iaW5lZF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkR3JvdXAuMSwKICBUb3RhbF9Db3VudCA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSR4LAogIFBvc2l0aXZlX0NvdW50ID0gcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHgsCiAgUmF0ZSA9IChwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCAvIHRvdGFsX2NvdW50c19ieV9zdGFnZSR4KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKKQpjb21iaW5lZF9kYXRhJFJhdGUgPC0gc3ByaW50ZigiJS4yZiUlIiwgY29tYmluZWRfZGF0YSRSYXRlKQpvdmVyYWxsX3RvdGFsX2NvdW50IDwtIG5yb3coY2lyY19kYXRhKQpvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IDwtIG5yb3coY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5vbkFDVCA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNTdXJ2ZWlsbGFuY2UgV2luZG93CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEuc3VydmVpbGxhbmNlICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnN1cnZlaWxsYW5jZSA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNQb3N0LUFDVCBXaW5kb3cKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5wb3N0QUNUIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucG9zdEFDVCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJIiwiSUkiLCJJSUkiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLnBvc3RBQ1QgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5wb3N0QUNUID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEucG9zdEFDVCwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49bGVuZ3RoKQpjb21iaW5lZF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkR3JvdXAuMSwKICBUb3RhbF9Db3VudCA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSR4LAogIFBvc2l0aXZlX0NvdW50ID0gcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHgsCiAgUmF0ZSA9IChwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCAvIHRvdGFsX2NvdW50c19ieV9zdGFnZSR4KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKKQpjb21iaW5lZF9kYXRhJFJhdGUgPC0gc3ByaW50ZigiJS4yZiUlIiwgY29tYmluZWRfZGF0YSRSYXRlKQpvdmVyYWxsX3RvdGFsX2NvdW50IDwtIG5yb3coY2lyY19kYXRhKQpvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IDwtIG5yb3coY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5wb3N0QUNUID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI1Bvc3QtcmVsYXBzZSBXaW5kb3cKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRjdEROQS5wb3N0UmVsYXBzZSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBvc3RSZWxhcHNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIkkiLCJJSSIsIklJSSIpKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgY3RETkEucG9zdFJlbGFwc2UgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5wb3N0UmVsYXBzZSA9PSAiUE9TSVRJVkUiLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1zdW0pCnRvdGFsX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLnBvc3RSZWxhcHNlLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3RSZWxhcHNlID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQpgYGAKCgoKCiNEZW1vZ3JhcGhpY3MgVGFibGUKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhX3N1YnNldCA8LSBjaXJjX2RhdGEgJT4lCiAgc2VsZWN0KAogICAgQWdlLAogICAgR2VuZGVyLAogICAgUHJpbVNpdGUsCiAgICBOQUMsCiAgICBOQUMuUmVnaW1lbiwKICAgIFRSRy5NYW5kYXJkLAogICAgVE5NLAogICAgU3RhZ2UsCiAgICBHcmFkZSwKICAgIExhdXJlbi5DbGFzcywKICAgIE1hcmdpbnMsCiAgICBBQ1QsCiAgICBBQ1QuUmVnaW1lbiwKICAgIERGUy5FdmVudCwKICAgIE9TLkV2ZW50LAogICAgRlUubW9udGhzKSAlPiUKICBtdXRhdGUoCiAgICBBZ2UgPSBhcy5udW1lcmljKEFnZSksCiAgICBHZW5kZXIgPSBmYWN0b3IoR2VuZGVyLCBsZXZlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSwKICAgIFByaW1TaXRlID0gZmFjdG9yKFByaW1TaXRlLCBsZXZlbHMgPSBjKCJTdG9tYWNoIiwgIkcvSiIsICJPZXNvcGhhZ3VzIikpLAogICAgTkFDID0gZmFjdG9yKE5BQywgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJOZW9hZGp1dmFudCBUaGVyYXB5IiwgIlVwZnJvbnQgU3VyZ2VyeSIpKSwKICAgIE5BQy5SZWdpbWVuID0gZmFjdG9yKE5BQy5SZWdpbWVuKSwKICAgIFRSRy5NYW5kYXJkID0gZmFjdG9yKFRSRy5NYW5kYXJkLCBsZXZlbHMgPSBjKCJUUkcxIiwiVFJHMiIsICJUUkczIiwgIlRSRzQiLCAiVFJHNSIpKSwKICAgIFROTSA9IGZhY3RvcihUTk0sIGxldmVscyA9IGMoIlQwLVRpc04wTTAiLCJUMS1UMk4wIiwgIlQyLVQzTjAtTjEiLCAiVDJOMS1OMiIsICJUM04yLU4zIiwgIlQ0TjAtTjEiLCAiVDROMi1OMyIpKSwKICAgIFN0YWdlID0gZmFjdG9yKFN0YWdlLCBsZXZlbHMgPSBjKCIwIiwiSSIsIklJIiwgIklJSSIpKSwKICAgIEdyYWRlID0gZmFjdG9yKEdyYWRlLCBsZXZlbHMgPSBjKCJHMSIsICJHMiIsICJHMyIpKSwKICAgIExhdXJlbi5DbGFzcyA9IGZhY3RvcihMYXVyZW4uQ2xhc3MpLAogICAgTWFyZ2lucyA9IGZhY3RvcihNYXJnaW5zLCBsZXZlbHMgPSBjKCJSMCIsICJSMSIpKSwKICAgIEFDVCA9IGZhY3RvcihBQ1QsIGxldmVscyA9IGMoIlRSVUUiLCAiRkFMU0UiKSwgbGFiZWxzID0gYygiQWRqdXZhbnQgVHJlYXRtZW50IiwgIk9ic2VydmF0aW9uIikpLAogICAgQUNULlJlZ2ltZW4gPSBmYWN0b3IoQUNULlJlZ2ltZW4pLAogICAgREZTLkV2ZW50ID0gZmFjdG9yKERGUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJSZWN1cnJlbmNlIiwgIk5vIFJlY3VycmVuY2UiKSksCiAgICBPUy5FdmVudCA9IGZhY3RvcihPUy5FdmVudCwgbGV2ZWxzID0gYygiVFJVRSIsICJGQUxTRSIpLCBsYWJlbHMgPSBjKCJEZWNlYXNlZCIsICJBbGl2ZSIpKSwKICAgIEZVLm1vbnRocyA9IGFzLm51bWVyaWMoRlUubW9udGhzKSkKdGFibGUxIDwtIGNpcmNfZGF0YV9zdWJzZXQgJT4lCiAgdGJsX3N1bW1hcnkoCiAgICBzdGF0aXN0aWMgPSBsaXN0KAogICAgICBhbGxfY29udGludW91cygpIH4gInttZWRpYW59ICh7bWlufSAtIHttYXh9KSIsCiAgICAgIGFsbF9jYXRlZ29yaWNhbCgpIH4gIntufSAoe3B9JSkiKSkgJT4lCiAgYm9sZF9sYWJlbHMoKQp0YWJsZTEKZml0MSA8LSBhc19mbGV4X3RhYmxlKAogIHRhYmxlMSwKICBpbmNsdWRlID0gZXZlcnl0aGluZygpLAogIHJldHVybl9jYWxscyA9IEZBTFNFLAogIHN0cmlwX21kX2JvbGQgPSBUUlVFKQpmaXQxCnNhdmVfYXNfZG9jeChmaXQxLCBwYXRoPSAifi9Eb3dubG9hZHMvdGFibGUxLmRvY3giKQpgYGAKCgojSGVhdG1hcCB3aXRoIENsaW5pY2FsICYgR2Vub21pY3MgRmFjdG9ycwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lIGFycmFuZ2UoU3RhZ2UpCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKaGEgPC0gSGVhdG1hcEFubm90YXRpb24oCiAgU3RhZ2UgPSBjaXJjX2RhdGEkU3RhZ2UsCiAgR2VuZGVyID0gY2lyY19kYXRhJEdlbmRlciwKICBQcmltU2l0ZSA9IGNpcmNfZGF0YSRQcmltU2l0ZSwKICBOQUMgPSBjaXJjX2RhdGEkTkFDLAogIEFDVCA9IGNpcmNfZGF0YSRBQ1QsCiAgY3RETkEuQmFzZSA9IGNpcmNfZGF0YSRjdEROQS5CYXNlLAogIGN0RE5BLkMyRDEgPSBjaXJjX2RhdGEkY3RETkEuQzJEMSwKICBjdEROQS5wb3N0TkFDID0gY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMsCiAgY3RETkEuTVJEID0gY2lyY19kYXRhJGN0RE5BLk1SRCwKICBjdEROQS5zdXJ2ZWlsbGFuY2UgPSBjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlLAogIERGUy5FdmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQsCiAgT1MuRXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQsCiAgCiAgY29sID0gbGlzdChTdGFnZSA9IGMoIjAiID0gInNlYWdyZWVuMSIsICJJIiA9ICJzZWFncmVlbjEiLCAiSUkiID0gIm9yYW5nZSIsICJJSUkiID0gInB1cnBsZSIpLAogICAgR2VuZGVyID0gYygiRmVtYWxlIiA9ICJnb2xkZW5yb2QiICwgIk1hbGUiID0gImJsdWU0IiksCiAgICBQcmltU2l0ZSA9IGMoIlN0b21hY2giID0gImJyb3duIiwgIkcvSiIgPSAiZGFya2dyZWVuIiwgIk9lc29waGFndXMiID0gIm9yYW5nZTQiKSwKICAgIE5BQyA9IGMoIkZBTFNFIiA9ICJjb3JuZmxvd2VyYmx1ZSIsICJUUlVFIiA9ImRhcmttYWdlbnRhIiksCiAgICBBQ1QgPSBjKCJUUlVFIiA9ICJicm93bjQiLCAiRkFMU0UiID0ia2hha2kiKSwKICAgIGN0RE5BLkJhc2UgPSBjKCJQT1NJVElWRSIgPSAicmVkMyIsICJORUdBVElWRSIgPSJibHVlIiksCiAgICBjdEROQS5DMkQxID0gYygiUE9TSVRJVkUiID0gInJlZDMiLCAiTkVHQVRJVkUiID0iYmx1ZSIpLAogICAgY3RETkEucG9zdE5BQyA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIGN0RE5BLk1SRCA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIGN0RE5BLnN1cnZlaWxsYW5jZSA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIERGUy5FdmVudCA9IGMoIlRSVUUiID0gInJlZDMiLCAiRkFMU0UiID0iYmx1ZSIpLAogICAgT1MuRXZlbnQgPSBjKCJUUlVFIiA9ICJibGFjayIsICJGQUxTRSIgPSJncmF5IikKKQopCmh0IDwtIEhlYXRtYXAobWF0cml4KG5yb3cgPSAwLCBuY29sID0gbGVuZ3RoKGNpcmNfZGF0YSRTdGFnZSkpLHNob3dfcm93X25hbWVzID0gRkFMU0UsY2x1c3Rlcl9yb3dzID0gRixjbHVzdGVyX2NvbHVtbnMgPSBGQUxTRSwgdG9wX2Fubm90YXRpb24gPSBoYSkKcGRmKCJoZWF0bWFwLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpkcmF3KGh0LCBhbm5vdGF0aW9uX2xlZ2VuZF9zaWRlID0gImJvdHRvbSIpCmRldi5vZmYoKQpgYGAKCgojT3ZlcnZpZXcgUGxvdApgYGB7cn0Kc2V0d2QoIn4vRG93bmxvYWRzIikgCmNsaW5zdGFnZTwtIHJlYWQuY3N2KCJQTEFHQVNUX09QLmNzdiIpCmNsaW5zdGFnZV9kZjwtIGFzLmRhdGEuZnJhbWUoY2xpbnN0YWdlKQoKI0Rpc3BsYXkgdGhlIHN3aW1tZXIgcGxvdCB3aXRoIHRoZSBsYWJlbCBib3gKb3Bsb3Q8LXN3aW1tZXJfcGxvdChkZj1jbGluc3RhZ2VfZGYsCiAgICAgICAgICAgICAgICAgICAgaWQ9J1BhdGllbnROYW1lJywKICAgICAgICAgICAgICAgICAgICBlbmQ9J2Z1LmRpZmYubW9udGhzJywKICAgICAgICAgICAgICAgICAgICBmaWxsPSdncmF5JywKICAgICAgICAgICAgICAgICAgICB3aWR0aD0uMDEsKQpvcGxvdCA8LSBvcGxvdCArIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSkKb3Bsb3QgPC0gb3Bsb3QgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0xMiwgOTYsIGJ5ID0gNikpCm9wbG90IDwtIG9wbG90ICsgbGFicyh4ID0iUGF0aWVudHMiICwgeT0iTW9udGhzIGZyb20gU3VyZ2VyeSIpCm9wbG90CgoKIyNwbG90IGV2ZW50cwpvcGxvdF9ldjEgPC0gb3Bsb3QgKyBzd2ltbWVyX3BvaW50cyhkZl9wb2ludHM9Y2xpbnN0YWdlX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZD0nUGF0aWVudE5hbWUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lPSdkYXRlLmRpZmYubW9udGhzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV9zaGFwZSA9J0V2ZW50X3R5cGUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lX2NvbCA9ICdFdmVudCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9My41LGZpbGw9J2JsYWNrJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2NvbD0nZGFya2dyZWVuJwopCm9wbG90X2V2MQoKI1NoYXBlIGN1c3RvbWl6YXRpb24gdG8gRXZlbnRfdHlwZQoKb3Bsb3RfZXYxLjEgPC0gb3Bsb3RfZXYxICsgZ2dwbG90Mjo6c2NhbGVfc2hhcGVfbWFudWFsKG5hbWU9IkV2ZW50X3R5cGUiLHZhbHVlcz1jKDEsMTYsNiwxOCw0KSxicmVha3M9YygnY3RETkFfbmVnJywnY3RETkFfcG9zJywnSW1hZ2luZycsJ1N1cmdlcnknLCdEZWF0aCcpKQoKb3Bsb3RfZXYxLjEKCiNwbG90IHRyZWF0bWVudAoKb3Bsb3RfZXYyIDwtIG9wbG90X2V2MS4xICsgc3dpbW1lcl9saW5lcyhkZl9saW5lcz1jbGluc3RhZ2VfZGYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9J1BhdGllbnROYW1lJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydD0nVHhfc3RhcnQubW9udGhzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ9J1R4X2VuZC5tb250aHMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVfY29sPSdUeF90eXBlJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTMuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lX2FscGhhID0gMS4wKQpvcGxvdF9ldjIgPC0gb3Bsb3RfZXYyICsgZ3VpZGVzKGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDUsIGNvbG9yID0gImJsYWNrIikpKQpvcGxvdF9ldjIgIAoKCiNjb2xvdXIgY3VzdG9taXphdGlvbgpvcGxvdF9ldjIuMiA8LSBvcGxvdF9ldjIgKyBnZ3Bsb3QyOjpzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0iRXZlbnQiLHZhbHVlcz1jKCAicHVycGxlIiwiYmxhY2siLCJibGFjayIsICJsaWdodGJsdWUiLCAiZ3JlZW4iLCAicmVkIiwgImJsdWUiLCJvcmFuZ2UiKSkKb3Bsb3RfZXYyLjIKYGBgCgoKI1JGUyBieSBjdEROQSBhdCBCYXNlbGluZSAtIGFsbCBzdGFnZXMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBCYXNlbGluZSB8IEFsbCBwdHMiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQmFzZSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkJhc2UsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5CYXNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBhdCBCYXNlbGluZSAtIGFsbCBzdGFnZXMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuQmFzZSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkJhc2UsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgQmFzZWxpbmUgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkJhc2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5CYXNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQmFzZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojUkZTIGJ5IGN0RE5BIGxldmVscyBhdCBCYXNlbGluZSBiYXNlZCBvbiBtZWRpYW4KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5CYXNlIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKIyBDYWxjdWxhdGUgdGhlIHF1YXJ0aWxlcyBvZiBwXzZtb19NVE0KY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSkpCm1lZGlhbl92YWx1ZSA8LSBtZWRpYW4oY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNLCBuYS5ybSA9IFRSVUUpCnByaW50KG1lZGlhbl92YWx1ZSkKCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHRoZXNlIHF1YXJ0aWxlcwoKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gTkEKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuNm1NVE0uUSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UuTVRNIDwgMC4zODUgfiAxLAogICAgY3RETkEuQmFzZS5NVE0gPj0gMC4zODUgfiAyCiAgKSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIE1UTS9tTCBncm91cHMgYXQgQmFzZWxpbmUiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIk1UTS9tTDwwLjM4NSIsICJNVE0vbUziiaUwLjM4NSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS42bU1UTS5RLCBsZXZlbHM9YygiMSIsIjIiKSwgbGFiZWxzID0gYygiTVRNL21MPDAuMzg1IiwgIk1UTS9tTOKJpTAuMzg1IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCiNPUyBieSBjdEROQSBsZXZlbHMgYXQgQmFzZWxpbmUgYmFzZWQgb24gbWVkaWFuCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiMgQ2FsY3VsYXRlIHRoZSBxdWFydGlsZXMgb2YgcF82bW9fTVRNCmNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0pKQptZWRpYW5fdmFsdWUgPC0gbWVkaWFuKGNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSwgbmEucm0gPSBUUlVFKQpwcmludChtZWRpYW5fdmFsdWUpCgojIENyZWF0ZSBhIG5ldyB2YXJpYWJsZSBiYXNlZCBvbiB0aGVzZSBxdWFydGlsZXMKCmNpcmNfZGF0YSRjdEROQS42bU1UTS5RIDwtIE5BCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLjZtTVRNLlEgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlLk1UTSA8IDAuMzg1IH4gMSwKICAgIGN0RE5BLkJhc2UuTVRNID49IDAuMzg1IH4gMgogICkpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS42bU1UTS5RLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVRNL21MIGdyb3VwcyBhdCBCYXNlbGluZSIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIk1UTS9tTDwwLjM4NSIsICJNVE0vbUziiaUwLjM4NSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS42bU1UTS5RLCBsZXZlbHM9YygiMSIsIjIiKSwgbGFiZWxzID0gYygiTVRNL21MPDAuMzg1IiwgIk1UTS9tTOKJpTAuMzg1IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCiNSRlMgYnkgY3RETkEgbGV2ZWxzIGF0IEJhc2VsaW5lIGJhc2VkIG9uIEFVQyBvcHRpbWFsIE1UTS9tbCBsZXZlbApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2UhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgojREZTLkV2ZW50CmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY29tcGxldGUuY2FzZXMoY2lyY19kYXRhJERGUy5FdmVudCwgY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKSxdCmNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSA8LSBhcy5udW1lcmljKGNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSkKUk9DIDwtIHJvYyhERlMuRXZlbnQgfiAgY3RETkEuQmFzZS5NVE0sIGRhdGEgPSBjaXJjX2RhdGEsIGNpID0gVFJVRSkKcDwtZ2dyb2MoUk9DLAogICAgICAgICBhZXMgPSBjKCJsaW5ldHlwZSIpLCBjb2xvciA9ICJibHVlIiwgIHNpemUgPSAxLAogICAgICAgICBsZWdhY3kuYXhlcyA9IFRSVUUpICsKICBnZW9tX2FibGluZShjb2xvciA9ICJkYXJrIGdyZXkiLCBzaXplID0gMC41KSArCiAgdGhlbWVfY2xhc3NpYygpKwogIHlsYWIoIlNlbnNpdGl2aXR5IikgKyB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xNCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTE0KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLCBzaXplPTE0KSxheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLHNpemU9MTQpLGxlZ2VuZC50aXRsZSAgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpCnAKCiNBVUMKQVVDIDwtIGF1YyhST0MpCnByaW50KEFVQykKQVVDX2NvbmYgPC0gY2kuYXVjKFJPQykKcHJpbnQoQVVDX2NvbmYpCnJlcy5yb2MgPC0gcm9jKGNpcmNfZGF0YSRERlMuRXZlbnQsIGNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSkKcGxvdC5yb2MocmVzLnJvYywgcHJpbnQuYXVjID0gVFJVRSwgcHJpbnQudGhyZXMgPSAiYmVzdCIpCgpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHRoZXNlIHF1YXJ0aWxlcwoKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuNm1NVE0uUSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UuTVRNIDwgMC44NDUgfiAxLAogICAgY3RETkEuQmFzZS5NVE0gPj0gMC44NDUgfiAyCiAgKSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuNm1NVE0uUSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIE1UTS9tTCBncm91cHMgYXQgQmFzZWxpbmUiLCB5bGFiPSAiRGlzZWFzZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIk1UTS9tTDwwLjg0NSIsICJNVE0vbUziiaUwLjg0NSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS42bU1UTS5RLCBsZXZlbHM9YygiMSIsIjIiKSwgbGFiZWxzID0gYygiTVRNL21MPDAuODQ1IiwgIk1UTS9tTOKJpTAuODQ1IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCiNPUyBieSBjdEROQSBsZXZlbHMgYXQgQmFzZWxpbmUgYmFzZWQgb24gQVVDIG9wdGltYWwgTVRNL21MIGxldmVsCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiNPUy5FdmVudApjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NvbXBsZXRlLmNhc2VzKGNpcmNfZGF0YSRPUy5FdmVudCwgY2lyY19kYXRhJGN0RE5BLkJhc2UuTVRNKSxdCmNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSA8LSBhcy5udW1lcmljKGNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSkKUk9DIDwtIHJvYyhPUy5FdmVudCB+ICBjdEROQS5CYXNlLk1UTSwgZGF0YSA9IGNpcmNfZGF0YSwgY2kgPSBUUlVFKQpwPC1nZ3JvYyhST0MsCiAgICAgICAgIGFlcyA9IGMoImxpbmV0eXBlIiksIGNvbG9yID0gImJsdWUiLCAgc2l6ZSA9IDEsCiAgICAgICAgIGxlZ2FjeS5heGVzID0gVFJVRSkgKwogIGdlb21fYWJsaW5lKGNvbG9yID0gImRhcmsgZ3JleSIsIHNpemUgPSAwLjUpICsKICB0aGVtZV9jbGFzc2ljKCkrCiAgeWxhYigiU2Vuc2l0aXZpdHkiKSArIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTE0KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIHNpemU9MTQpLGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xNCksbGVnZW5kLnRpdGxlICA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKcAoKI0FVQwpBVUMgPC0gYXVjKFJPQykKcHJpbnQoQVVDKQpBVUNfY29uZiA8LSBjaS5hdWMoUk9DKQpwcmludChBVUNfY29uZikKcmVzLnJvYyA8LSByb2MoY2lyY19kYXRhJE9TLkV2ZW50LCBjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0pCnBsb3Qucm9jKHJlcy5yb2MsIHByaW50LmF1YyA9IFRSVUUsIHByaW50LnRocmVzID0gImJlc3QiKQoKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2UhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgojIENyZWF0ZSBhIG5ldyB2YXJpYWJsZSBiYXNlZCBvbiB0aGVzZSBxdWFydGlsZXMKCmNpcmNfZGF0YSRjdEROQS42bU1UTS5RIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLjZtTVRNLlEgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlLk1UTSA8IDExLjMwNSB+IDEsCiAgICBjdEROQS5CYXNlLk1UTSA+PSAxMS4zMDUgfiAyCiAgKSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLjZtTVRNLlEsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBNVE0vbUwgZ3JvdXBzIGF0IEJhc2VsaW5lIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiTVRNL21MPDExLjMwNSIsICJNVE0vbUziiaUxMS4zMDUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS42bU1UTS5RIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSwgbGV2ZWxzPWMoIjEiLCIyIiksIGxhYmVscyA9IGMoIk1UTS9tTDwxMS4zMDUiLCAiTVRNL21M4omlMTEuMzA1IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCiNPUyBieSBjdEROQSBsZXZlbHMgYXQgQmFzZWxpbmUgYmFzZWQgb24gQVVDIG9wdGltYWwgTVRNL21MIGxldmVsIGZyb20gUkZTIG1vZGVsCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQmFzZSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHRoZXNlIHF1YXJ0aWxlcwoKY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuNm1NVE0uUSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UuTVRNIDwgMC44NDUgfiAxLAogICAgY3RETkEuQmFzZS5NVE0gPj0gMC44NDUgfiAyCiAgKSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLjZtTVRNLlEsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS42bU1UTS5RLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBNVE0vbUwgZ3JvdXBzIGF0IEJhc2VsaW5lIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiTVRNL21MPDAuODQ1IiwgIk1UTS9tTOKJpTAuODQ1IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuNm1NVE0uUSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLjZtTVRNLlEsIGxldmVscz1jKCIxIiwiMiIpLCBsYWJlbHMgPSBjKCJNVE0vbUw8MC44NDUiLCAiTVRNL21M4omlMC44NDUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLjZtTVRNLlEsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKI1JGUyBieSBjdEROQSBvbi1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzJEMSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuQzJEMSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgc3RhdHVzIG9uLU5BVCB8IEFsbCBwdHMiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkMyRDEsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBvbi1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzJEMSE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLkMyRDEsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIHN0YXR1cyBvbi1OQVQgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkMyRDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojREZTIGJ5IGN0RE5BIENsZWFyYW5jZSBkdXJpbmcgTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DMkQxLkNsZWFyYW5jZSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiB+ICJUUlVFIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiB+ICJGQUxTRSIsCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIGNsZWFyYW5jZSBDMkQxIiwgeWxhYj0gIlJlY3VycmVuY2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIFN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJObyBDbGVhcmFuY2UiLCAiQ2xlYXJhbmNlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNPUyBieSBjdEROQSBDbGVhcmFuY2UgZHVyaW5nIE5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuQzJEMS5DbGVhcmFuY2UgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJORUdBVElWRSIgfiAiVFJVRSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgfiAiRkFMU0UiLAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9Ik9TIC0gY3RETkEgY2xlYXJhbmNlIEMyRDEiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIFN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJObyBDbGVhcmFuY2UiLCAiQ2xlYXJhbmNlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNSRlMgYnkgY3RETkEgcG9zdC1OQVQgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgc3RhdHVzIHBvc3QtTkFUIHwgQWxsIHB0cyIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygyNCkpCmNpcmNfZGF0YSRjdEROQS5wb3N0TkFDIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucG9zdE5BQywgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLnBvc3ROQUMsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCgoKI09TIGJ5IGN0RE5BIHBvc3QtTkFUIC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5wb3N0TkFDLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBzdGF0dXMgcG9zdC1OQVQgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wb3N0TkFDLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQywgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojTXVsdGl2YXJpYXRlIGNveCByZWdyZXNzaW9uIGZvciBSRlMgLSBjdEROQSBwb3N0LU5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEucG9zdE5BQyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIiksIGxhYmVscyA9IGMoIk5lZ2F0aXZlIiwgIlBvc2l0aXZlIikpCmNpcmNfZGF0YSRQcmltU2l0ZSA8LSBmYWN0b3IoY2lyY19kYXRhJFByaW1TaXRlLCBsZXZlbHM9YygiRy9KIiwiU3RvbWFjaCIpKQpjaXJjX2RhdGEkR2VuZGVyIDwtIGZhY3RvcihjaXJjX2RhdGEkR2VuZGVyLCBsZXZlbHM9YygiTWFsZSIsIkZlbWFsZSIpKQpjaXJjX2RhdGEkQWdlLkdyb3VwIDwtIGZhY3RvcihjaXJjX2RhdGEkQWdlLkdyb3VwLCBsZXZlbHM9YygiMiIsIjEiKSwgbGFiZWxzID0gYygiPjcwIiwgIuKJpDcwIikpCmNpcmNfZGF0YSR5cE5TdGF0dXMgPC0gZmFjdG9yKGNpcmNfZGF0YSR5cE5TdGF0dXMsIGxldmVscz1jKCJOMCIsIk4xLU4zIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscz1jKCJUUkcxLzIvMyIsIlRSRzQvNSIpKQpjaXJjX2RhdGEkQUNUIDwtIGZhY3RvcihjaXJjX2RhdGEkQUNULCBsZXZlbHM9YygiVFJVRSIsIkZBTFNFIikpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpIApjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQyArIFByaW1TaXRlICsgR2VuZGVyICsgQWdlLkdyb3VwICsgQUNULCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsIGRhdGEgPSBjaXJjX2RhdGEsIG1haW4gPSAiTXVsdGl2YXJpYXRlIFJlZ3Jlc3Npb24gTW9kZWwgZm9yIFJGUyIsIHJlZkxhYmVsID0gIlJlZmVyZW5jZSBHcm91cCIpCnRlc3QucGggPC0gY294LnpwaChjb3hfZml0KQpgYGAKCgojTXVsdGl2YXJpYXRlIGNveCByZWdyZXNzaW9uIGZvciBPUyAtIGN0RE5BIHBvc3QtTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5wb3N0TkFDIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucG9zdE5BQywgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSwgbGFiZWxzID0gYygiTmVnYXRpdmUiLCAiUG9zaXRpdmUiKSkKY2lyY19kYXRhJFByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkUHJpbVNpdGUsIGxldmVscz1jKCJHL0oiLCJTdG9tYWNoIikpCmNpcmNfZGF0YSRHZW5kZXIgPC0gZmFjdG9yKGNpcmNfZGF0YSRHZW5kZXIsIGxldmVscz1jKCJNYWxlIiwiRmVtYWxlIikpCmNpcmNfZGF0YSRBZ2UuR3JvdXAgPC0gZmFjdG9yKGNpcmNfZGF0YSRBZ2UuR3JvdXAsIGxldmVscz1jKCIyIiwiMSIpLCBsYWJlbHMgPSBjKCI+NzAiLCAi4omkNzAiKSkKY2lyY19kYXRhJHlwTlN0YXR1cyA8LSBmYWN0b3IoY2lyY19kYXRhJHlwTlN0YXR1cywgbGV2ZWxzPWMoIk4wIiwiTjEtTjMiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzPWMoIlRSRzEvMi8zIiwiVFJHNC81IikpCmNpcmNfZGF0YSRBQ1QgPC0gZmFjdG9yKGNpcmNfZGF0YSRBQ1QsIGxldmVscz1jKCJUUlVFIiwiRkFMU0UiKSkKc3Vydl9vYmplY3QgPC0gU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpIApjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEucG9zdE5BQyArIFByaW1TaXRlICsgR2VuZGVyICsgQWdlLkdyb3VwICsgQUNULCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsIGRhdGEgPSBjaXJjX2RhdGEsIG1haW4gPSAiTXVsdGl2YXJpYXRlIFJlZ3Jlc3Npb24gTW9kZWwgZm9yIE9TIiwgcmVmTGFiZWwgPSAiUmVmZXJlbmNlIEdyb3VwIikKdGVzdC5waCA8LSBjb3guenBoKGNveF9maXQpCmBgYAoKCiNSRlMgYnkgY3RETkEgcG9zdC1OQVQgJiB5cFQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5wb3N0TkFDIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiAzLAogICAgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJERlMgLSBjdEROQSBwb3N0LU5BVCAmIHlwVE4iLCB5bGFiPSAiRGlzZWFzZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIFN1cmdlcnkgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIxIiwiMiIsIjMiLCI0IiksIGxhYmVscyA9IGMoImN0RE5BKC0pICYgVDEtVDMiLCAiY3RETkEoKykgJiBUMS1UMyIsICJjdEROQSgtKSAmIFQ0IiwgImN0RE5BKCspICYgVDQiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCgojUmVwZWF0IGFuYWx5c2lzIHRvIGNvbXBhcmUgY3RETkEgcG9zdC1OQVQgKCspIFQxLVQzIHZzIFQ0CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5wb3N0TkFDIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiAzLAogICAgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIyIiwiNCIsIjEiLCIzIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNPUyBieSBjdEROQSBwb3N0LU5BVCAmIHlwVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMSwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAyLAogICAgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDMsCiAgICBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicHVycGxlIiwgInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBwb3N0LU5BVCAmIHlwVE4iLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBTdXJnZXJ5IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEoLSkgJiBUMS1UMyIsICJjdEROQSgrKSAmIFQxLVQzIiwgImN0RE5BKC0pICYgVDQiLCAiY3RETkEoKykgJiBUNCIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQoKI1JlcGVhdCBhbmFseXNpcyB0byBjb21wYXJlIGN0RE5BIHBvc3QtTkFUICgrKSBUMS1UMyB2cyBUNApybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAxLAogICAgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDIsCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gMywKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiA0CiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIyIiwiNCIsIjEiLCIzIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNSRlMgYnkgY3RETkEgcG9zdC1OQVQgJiB5cE4KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5wb3N0TkFDIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiICYgeXBOU3RhdHVzID09ICJOMCIgfiAxLAogICAgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiICYgeXBOU3RhdHVzID09ICJOMCIgfiAyLAogICAgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiICYgeXBOU3RhdHVzID09ICJOMS1OMyIgfiAzLAogICAgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiICYgeXBOU3RhdHVzID09ICJOMS1OMyIgfiA0CiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicHVycGxlIiwgInJlZCIpLCB0aXRsZT0iREZTIC0gY3RETkEgcG9zdC1OQVQgJiB5cE4iLCB5bGFiPSAiRGlzZWFzZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIFN1cmdlcnkgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIsIjQiKSwgbGFiZWxzID0gYygiY3RETkEoLSkgJiB5cE4wIiwgImN0RE5BKCspICYgeXBOMCIsICJjdEROQSgtKSAmIHlwTisiLCAiY3RETkEoKykgJiB5cE4rIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQoKI1JlcGVhdCBhbmFseXNpcyB0byBjb21wYXJlIGN0RE5BIHBvc3QtTkFUICgtKSB2cyAoKykgaW4geXBOKwpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMSwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gMywKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSwgbGV2ZWxzPWMoIjMiLCI0IiwiMSIsIjIiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmBgYAoKI09TIGJ5IGN0RE5BIHBvc3QtTkFUICYgeXBOCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEucG9zdE5BQyE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMSwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gMywKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicHVycGxlIiwgInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBwb3N0LU5BVCAmIHlwTiIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIFN1cmdlcnkgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIsIjQiKSwgbGFiZWxzID0gYygiY3RETkEoLSkgJiB5cE4wIiwgImN0RE5BKCspICYgeXBOMCIsICJjdEROQSgtKSAmIHlwTisiLCAiY3RETkEoKykgJiB5cE4rIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQoKI1JlcGVhdCBhbmFseXNpcyB0byBjb21wYXJlIGN0RE5BIHBvc3QtTkFUICgrKSB5cE4wIHZzIHlwTisKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnBvc3ROQUMhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4wIiB+IDEsCiAgICBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4wIiB+IDIsCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDMsCiAgICBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIyIiwiNCIsIjEiLCIzIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNERlMgYnkgY3RETkEgQ2xlYXJhbmNlIHBvc3QtTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DMkQxLkNsZWFyYW5jZSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJUUlVFIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiB+ICJGQUxTRSIsCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpfmN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoInJlZCIsImJsdWUiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIGNsZWFyYW5jZSBwb3N0LU5BVCIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBTdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiTm8gQ2xlYXJhbmNlIiwgIkNsZWFyYW5jZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDI0KSkKY2lyY19kYXRhJGN0RE5BLkMyRDEuQ2xlYXJhbmNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UsIGxldmVscz1jKCJUUlVFIiwiRkFMU0UiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgojT1MgYnkgY3RETkEgQ2xlYXJhbmNlIHBvc3QtTkFUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DMkQxLkNsZWFyYW5jZSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJUUlVFIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiB+ICJGQUxTRSIsCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5DMkQxLkNsZWFyYW5jZSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkMyRDEuQ2xlYXJhbmNlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygicmVkIiwiYmx1ZSIpLCB0aXRsZT0iT1MgLSBjdEROQSBjbGVhcmFuY2UgcG9zdC1OQVQiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIFN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJObyBDbGVhcmFuY2UiLCAiQ2xlYXJhbmNlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMjQpKQpjaXJjX2RhdGEkY3RETkEuQzJEMS5DbGVhcmFuY2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DMkQxLkNsZWFyYW5jZSwgbGV2ZWxzPWMoIlRSVUUiLCJGQUxTRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzJEMS5DbGVhcmFuY2UsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNBc3NvY2lhdGlvbiBvZiBjdEROQSBEeW5hbWljcyBwb3N0LU5BVCBhbmQgUmVzcG9uc2UKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLkR5bmFtaWNzID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiTkVHQVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvLS8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLysvLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiY3RETkEgKy8rLysiCiAgKSkKCiNWZXJ0aWNhbCBGaXNoZXIgcGxvdCBmb3IgY3RETkEgY2xlYXJhbmNlIHBvc3QtTkFUIGFuZCBSZWMgU3RhdHVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEpCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzLCBsZXZlbHM9YygiY3RETkEgKy8tLy0iLCAiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzID0gYygiVFJHMS8yLzMiLCAiVFJHNC81IikpCmNvbnRpbmdlbmN5X3RhYmxlIDwtIHRhYmxlKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgY2lyY19kYXRhJFRSRykKZmlzaGVyX2V4YWN0X3Rlc3QgPC0gZmlzaGVyLnRlc3QoY29udGluZ2VuY3lfdGFibGUpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCnByaW50KGZpc2hlcl9leGFjdF90ZXN0KQpwcmludChjb250aW5nZW5jeV90YWJsZSkKdGFibGVfZGYgPC0gYXMuZGF0YS5mcmFtZShjb250aW5nZW5jeV90YWJsZSkKdGFibGVfZGYkVG90YWwgPC0gYXZlKHRhYmxlX2RmJEZyZXEsIHRhYmxlX2RmJFZhcjEsIEZVTiA9IHN1bSkKdGFibGVfZGYkUGVyY2VudGFnZSA8LSB0YWJsZV9kZiRGcmVxIC8gdGFibGVfZGYkVG90YWwKdGFibGVfZGYkTWlkZGxlUGVyY2VudGFnZSA8LSB0YWJsZV9kZiRQZXJjZW50YWdlIC8gMgoKIyBTd2FwcGluZyB4IGFuZCB5IGluIGdncGxvdCBmdW5jdGlvbiB0byBtYWtlIGJhciBwbG90IHZlcnRpY2FsCmdncGxvdCh0YWJsZV9kZiwgYWVzKHkgPSBWYXIxLCB4ID0gUGVyY2VudGFnZSwgZmlsbCA9IFZhcjIpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3RleHQoYWVzKHggPSBNaWRkbGVQZXJjZW50YWdlLCBsYWJlbCA9IEZyZXEpLCBwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAxLjUsIHNpemUgPSA3KSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gImN0RE5BIER5bWFtaWNzIHBvc3QtTkFUIiwgeSA9ICJjdEROQSIsIHggPSAiUGF0aWVudHMgKCUpIiwgZmlsbCA9ICJQYXRoIFJlc3BvbnNlIikgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUUkcxLzIvMyIgPSAibGlnaHRibHVlMyIsICJUUkc0LzUiID0gInJlZCIpKSArICMgZGVmaW5lIGN1c3RvbSBjb2xvcnMKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTQpLCAjIGluY3JlYXNlIHktYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeC1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIGxhYmVsIHNpemUKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHgtYXhpcyBsYWJlbCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpKSAgIyBpbmNyZWFzZSBSZWN1cnJlbmNlIGxhYmVsIHNpemUKCiNDYWxjdWxhdGluZyBwLXZhbHVlIHdpdGggRmlzaGVyIGV4YWN0IHRlc3QgZm9yIHRoZSBjdEROQSArLysvKyB2cyBjdEROQSArLysvLQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5EeW5hbWljcyA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIk5FR0FUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLy0vLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8rLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiUE9TSVRJVkUiIH4gImN0RE5BICsvKy8rIgogICkpCgojVmVydGljYWwgRmlzaGVyIHBsb3QgZm9yIGN0RE5BIGNsZWFyYW5jZSBwb3N0LU5BVCBhbmQgUmVjIFN0YXR1cwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyE9IiIsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5EeW5hbWljcyE9ImN0RE5BICsvLS8tIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEpCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzLCBsZXZlbHM9YygiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzID0gYygiVFJHMS8yLzMiLCAiVFJHNC81IikpCmNvbnRpbmdlbmN5X3RhYmxlIDwtIHRhYmxlKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgY2lyY19kYXRhJFRSRykKZmlzaGVyX2V4YWN0X3Rlc3QgPC0gZmlzaGVyLnRlc3QoY29udGluZ2VuY3lfdGFibGUpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCnByaW50KGZpc2hlcl9leGFjdF90ZXN0KQpwcmludChjb250aW5nZW5jeV90YWJsZSkKYGBgCgoKI0RGUyBieSBjdEROQSBEeW5hbWljcyBwb3N0LU5BVApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCgpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuRHluYW1pY3MgPSBjYXNlX3doZW4oCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJORUdBVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgfiAiY3RETkEgKy8tLy0iLAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiUE9TSVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvKy8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiB+ICJjdEROQSArLysvKyIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzKSxdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBEeW5hbWljcyBwb3N0LU5BVCIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgKy8tLy0iLCJjdEROQSArLysvLSIsICJjdEROQSArLysvKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvLS8tIiwiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkR5bmFtaWNzLCBkYXRhPWNpcmNfZGF0YSkKc3VtbWFyeShjb3hfZml0KQpgYGAKCgojT1MgYnkgY3RETkEgRHluYW1pY3MgcG9zdC1OQVQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLkR5bmFtaWNzID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiTkVHQVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvLS8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLysvLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiY3RETkEgKy8rLysiCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5EeW5hbWljcywgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsImdyZWVuIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIER5bmFtaWNzIHBvc3QtTkFUIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiY3RETkEgKy8tLy0iLCJjdEROQSArLysvLSIsICJjdEROQSArLysvKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvLS8tIiwiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSkKY294X2ZpdCA8LSBjb3hwaGYoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI0xldmVscyBvZiBCYXNlbGluZSBNVE0vbUwgaW4gY3RETkEgRHluYW1pY3MgcG9zdC1OQVQgY2F0ZWdvcmllcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkJhc2UhPSIiLF0KY2lyY19kYXRhIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLkR5bmFtaWNzID0gY2FzZV93aGVuKAogICAgY3RETkEuQmFzZSA9PSAiUE9TSVRJVkUiICYgY3RETkEuQzJEMSA9PSAiTkVHQVRJVkUiICYgY3RETkEucG9zdE5BQyA9PSAiTkVHQVRJVkUiIH4gImN0RE5BICsvLS8tIiwKICAgIGN0RE5BLkJhc2UgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLkMyRDEgPT0gIlBPU0lUSVZFIiAmIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiB+ICJjdEROQSArLysvLSIsCiAgICBjdEROQS5CYXNlID09ICJQT1NJVElWRSIgJiBjdEROQS5DMkQxID09ICJQT1NJVElWRSIgJiBjdEROQS5wb3N0TkFDID09ICJQT1NJVElWRSIgfiAiY3RETkEgKy8rLysiCiAgKSkKCiMgVHJhbnNmb3JtIGN0RE5BLkJhc2UuTVRNIHdpdGggbG9nMTAKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsICFpcy5uYShjdEROQS5EeW5hbWljcykpCmNpcmNfZGF0YSRjdEROQS5CYXNlLk1UTSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihjaXJjX2RhdGEkY3RETkEuQmFzZS5NVE0pKQpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzPWMoImN0RE5BICsvLS8tIiwiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSkKbWVkaWFuX0Jhc2VfTVRNIDwtIGFnZ3JlZ2F0ZShjdEROQS5CYXNlLk1UTSB+IGN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhLCBGVU4gPSBtZWRpYW4pCnByaW50KG1lZGlhbl9CYXNlX01UTSkKCiMgQ3JlYXRlIHZpb2xpbiBwbG90IHdpdGggbG9nMTAgc2NhbGUgb24geS1heGlzCmdncGxvdChjaXJjX2RhdGEsIGFlcyh4PWN0RE5BLkR5bmFtaWNzLCB5PWN0RE5BLkJhc2UuTVRNLCBmaWxsPWN0RE5BLkR5bmFtaWNzKSkgKwogIGdlb21fdmlvbGluKHRyaW09RkFMU0UpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiY3RETkEgKy8tLy0iPSJsaWdodGJsdWUiLCAiY3RETkEgKy8rLy0iPSJsaWdodGdyZWVuIiwgImN0RE5BICsvKy8rIj0ic2FsbW9uIikpICsKICBnZW9tX2JveHBsb3Qod2lkdGg9MC4xLCBmaWxsPSJ3aGl0ZSIsIGNvbG91cj0iYmxhY2siLCBhbHBoYT0wLjUpICsKICBzY2FsZV95X2xvZzEwKGJyZWFrcz1jKDAuMDAxLCAwLjAxLCAwLjEsIDEsIDEwLCAxMDAsIDEwMDAsIDEwMDAwKSkgKwogIGxhYnModGl0bGU9IkJhc2VsaW5lIE1UTS9tTCB8IER5bmFtaWNzIHBvc3QtTkFUIiwgeD0iRHluYW1pY3MgcG9zdC1OQVQiLCB5PSJCYXNlbGluZSBNVE0vbUwiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQptM18xdjIgPC0gd2lsY294LnRlc3QoY3RETkEuQmFzZS5NVE0gfiBjdEROQS5EeW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzICVpbiUgYygiY3RETkEgKy8tLy0iLCAiY3RETkEgKy8rLy0iKSwgXSwKICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSkKcHJpbnQobTNfMXYyKQptM18xdjMgPC0gd2lsY294LnRlc3QoY3RETkEuQmFzZS5NVE0gfiBjdEROQS5EeW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzICVpbiUgYygiY3RETkEgKy8tLy0iLCAiY3RETkEgKy8rLysiKSwgXSwKICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSkKcHJpbnQobTNfMXYzKQptM18ydjMgPC0gd2lsY294LnRlc3QoY3RETkEuQmFzZS5NVE0gfiBjdEROQS5EeW5hbWljcywKICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzICVpbiUgYygiY3RETkEgKy8rLy0iLCAiY3RETkEgKy8rLysiKSwgXSwKICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSkKcHJpbnQobTNfMnYzKQpgYGAKCiNERlMgYnkgY3RETkEgcG9zdC1OQVQgJiBUUkcgY29tYmluYXRpb24KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5wQ1IgPSBjYXNlX3doZW4oCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiBUUkcgPT0gIlRSRzEvMi8zIiB+ICIxIiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIFRSRyA9PSAiVFJHNC81IiB+ICIyIiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIFRSRyA9PSAiVFJHNC81IiB+ICIzIgogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEucENSKSxdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEucENSLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJyZWQiKSwgdGl0bGU9IlJGUyAtIGN0RE5BIHBvc3QtTkFUL1RSRyIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiVFJHMS8yLzMgY3RETkEgKC0pIiwiVFJHNC81IGN0RE5BICgtKSIsICJUUkc0LzUgY3RETkEgKCspIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5wQ1IgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wQ1IsIGxldmVscz1jKCIxIiwiMiIsIjMiKSwgbGFiZWxzPWMoIlRSRzEvMi8zIGN0RE5BICgtKSIsIlRSRzQvNSBjdEROQSAoLSkiLCAiVFJHNC81IGN0RE5BICgrKSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEucENSLCBkYXRhPWNpcmNfZGF0YSkKc3VtbWFyeShjb3hfZml0KQpgYGAKCgojT1MgYnkgY3RETkEgcG9zdC1OQVQgJiBUUkcgY29tYmluYXRpb24KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQoKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5wQ1IgPSBjYXNlX3doZW4oCiAgICBjdEROQS5wb3N0TkFDID09ICJORUdBVElWRSIgJiBUUkcgPT0gIlRSRzEvMi8zIiB+ICIxIiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIk5FR0FUSVZFIiAmIFRSRyA9PSAiVFJHNC81IiB+ICIyIiwKICAgIGN0RE5BLnBvc3ROQUMgPT0gIlBPU0lUSVZFIiAmIFRSRyA9PSAiVFJHNC81IiB+ICIzIgogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhWyFpcy5uYShjaXJjX2RhdGEkY3RETkEucENSKSxdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBwb3N0LU5BVC9UUkciLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJUUkcxLzIvMyBjdEROQSAoLSkiLCJUUkc0LzUgY3RETkEgKC0pIiwgIlRSRzQvNSBjdEROQSAoKykiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBDUiwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIpLCBsYWJlbHM9YygiVFJHMS8yLzMgY3RETkEgKC0pIiwiVFJHNC81IGN0RE5BICgtKSIsICJUUkc0LzUgY3RETkEgKCspIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmBgYAoKCiNERlMgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRERlMubW9udGhzPWNpcmNfZGF0YSRERlMubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgTVJEIHdpbmRvdyB8IEFsbCBwdHMiLCB5bGFiPSAiUmVjdXJyZW5jZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsIDI0KSkKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKCgojT1MgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgLSBhbGwgc3RhZ2VzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRGVS5tb250aHM9Y2lyY19kYXRhJEZVLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEZVLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuTVJELCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuTVJELCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9NiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIE1SRCB3aW5kb3cgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuTVJELCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCgojUkZTIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93ICYgeXBUCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRERlMubW9udGhzPWNpcmNfZGF0YSRERlMubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMSwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDIsCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiAzLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIE1SRCAmIHlwVE4iLCB5bGFiPSAiRGlzZWFzZS1GcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIxIiwiMiIsIjMiLCI0IiksIGxhYmVscyA9IGMoImN0RE5BKC0pICYgVDEtVDMiLCAiY3RETkEoKykgJiBUMS1UMyIsICJjdEROQSgtKSAmIFQ0IiwgImN0RE5BKCspICYgVDQiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCgojUmVwZWF0IGFuYWx5c2lzIHRvIGNvbXBhcmUgY3RETkEgTVJEICgtKSB2cyAoKykgaW4gVDQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gMywKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJERlMgLSBjdEROQSBNUkQgJiB5cFROIiwgeWxhYj0gIkRpc2Vhc2UtRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEoLSkgJiBUMS1UMyIsICJjdEROQSgrKSAmIFQxLVQzIiwgImN0RE5BKC0pICYgVDQiLCAiY3RETkEoKykgJiBUNCIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMiIsIjQiLCIxIiwiMyIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuU3RhZ2UuSUkuVE5NLCBkYXRhPWNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKYGBgCgojT1MgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cFQKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJEZVLm1vbnRocz1jaXJjX2RhdGEkRlUubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAxLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiBwVC5TdGFnZSA9PSAiVDEtVDMiIH4gMiwKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDMsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUNCIgfiA0CiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlROTSE9IiIsXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIE1SRCAmIHlwVE4iLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEoLSkgJiBUMS1UMyIsICJjdEROQSgrKSAmIFQxLVQzIiwgImN0RE5BKC0pICYgVDQiLCAiY3RETkEoKykgJiBUNCIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQoKI1JlcGVhdCBhbmFseXNpcyB0byBjb21wYXJlIGN0RE5BIHBvc3QtTkFUICgtKSB2cyAoKykgaW4gVDQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGEkRlUubW9udGhzPWNpcmNfZGF0YSRGVS5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRGVS5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5SaXNrIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLlN0YWdlLklJLlROTSA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQxLVQzIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHBULlN0YWdlID09ICJUMS1UMyIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZSA9PSAiVDQiIH4gMywKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgcFQuU3RhZ2UgPT0gIlQ0IiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEICYgeXBUTiIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSgtKSAmIFQxLVQzIiwgImN0RE5BKCspICYgVDEtVDMiLCAiY3RETkEoLSkgJiBUNCIsICJjdEROQSgrKSAmIFQ0IiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwyNCkpCmNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0gPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0sIGxldmVscz1jKCIyIiwiNCIsIjEiLCIzIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5TdGFnZS5JSS5UTk0sIGRhdGE9Y2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCiNSRlMgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cE4KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJERGUy5tb250aHM9Y2lyY19kYXRhJERGUy5tb250aHMtMwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRERlMubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuUmlzayA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5TdGFnZS5JSS5UTk0gPSBjYXNlX3doZW4oCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMSwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgeXBOU3RhdHVzID09ICJOMCIgfiAyLAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDMsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gNAogICkpCgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5TdGFnZS5JSS5UTk0hPSIiLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5TdGFnZS5JSS5UTk0sIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIE1SRCAmIHlwTiIsIHlsYWI9ICJEaXNlYXNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BKC0pICYgeXBOMCIsICJjdEROQSgrKSAmIHlwTjAiLCAiY3RETkEoLSkgJiB5cE4rIiwgImN0RE5BKCspICYgeXBOKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmBgYAoKI09TIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93ICYgeXBOCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YSRGVS5tb250aHM9Y2lyY19kYXRhJEZVLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEZVLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLlN0YWdlLklJLlJpc2sgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuU3RhZ2UuSUkuVE5NID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4wIiB+IDEsCiAgICBjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gMiwKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgeXBOU3RhdHVzID09ICJOMS1OMyIgfiAzLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiB5cE5TdGF0dXMgPT0gIk4xLU4zIiB+IDQKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIT0iIixdCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEICYgeXBOIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BKC0pICYgeXBOMCIsICJjdEROQSgrKSAmIHlwTjAiLCAiY3RETkEoLSkgJiB5cE4rIiwgImN0RE5BKCspICYgeXBOKyIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuU3RhZ2UuSUkuVE5NLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSAmIHlwTjAiLCAiY3RETkEoKykgJiB5cE4wIiwgImN0RE5BKC0pICYgeXBOKyIsICJjdEROQSgrKSAmIHlwTisiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLlN0YWdlLklJLlROTSwgZGF0YT1jaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmBgYAoKI0RGUyBieSBjdEROQSBhdCB0aGUgTVJEIFdpbmRvdyAmIFRSRyBjb21iaW5hdGlvbgpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSRERlMubW9udGhzPWNpcmNfZGF0YSRERlMubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkREZTLm1vbnRocz49MCxdCgpjaXJjX2RhdGEkY3RETkEucENSIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLnBDUiA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgVFJHID09ICJUUkcxLzIvMyIgfiAiMSIsCiAgICBjdEROQS5NUkQgPT0gIk5FR0FUSVZFIiAmIFRSRyA9PSAiVFJHNC81IiB+ICIyIiwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiICYgVFJHID09ICJUUkc0LzUiIH4gIjMiCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5wQ1IpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInJlZCIpLCB0aXRsZT0iUkZTIC0gY3RETkEgTVJEL1RSRyIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoIlRSRzEvMi8zIGN0RE5BICgtKSIsIlRSRzQvNSBjdEROQSAoLSkiLCAiVFJHNC81IGN0RE5BICgrKSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsMjQpKQpjaXJjX2RhdGEkY3RETkEucENSIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEucENSLCBsZXZlbHM9YygiMSIsIjIiLCIzIiksIGxhYmVscz1jKCJUUkcxLzIvMyBjdEROQSAoLSkiLCJUUkc0LzUgY3RETkEgKC0pIiwgIlRSRzQvNSBjdEROQSAoKykiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI09TIGJ5IGN0RE5BIGF0IHRoZSBNUkQgV2luZG93ICYgVFJHIGNvbWJpbmF0aW9uCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhJEZVLm1vbnRocz1jaXJjX2RhdGEkRlUubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzPj0wLF0KCmNpcmNfZGF0YSRjdEROQS5wQ1IgPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEucENSID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBUUkcgPT0gIlRSRzEvMi8zIiB+ICIxIiwKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgVFJHID09ICJUUkc0LzUiIH4gIjIiLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgJiBUUkcgPT0gIlRSRzQvNSIgfiAiMyIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLnBDUiksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgTVJEL1RSRyIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSBmcm9tIExhbmRtYXJrIFRpbWUgcG9pbnQgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJUUkcxLzIvMyBjdEROQSAoLSkiLCJUUkc0LzUgY3RETkEgKC0pIiwgIlRSRzQvNSBjdEROQSAoKykiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLDI0KSkKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBDUiwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIpLCBsYWJlbHM9YygiVFJHMS8yLzMgY3RETkEgKC0pIiwiVFJHNC81IGN0RE5BICgtKSIsICJUUkc0LzUgY3RETkEgKCspIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmBgYAoKCiNERlMgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cFROIENoYXJhY3RlcmlzdGljcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZCA9PSBUUlVFLF0KY2lyY19kYXRhJERGUy5tb250aHMgPC0gY2lyY19kYXRhJERGUy5tb250aHMgLSAzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHMgPj0gMCxdCmNpcmNfZGF0YSRjdEROQS5wQ1IgPC0gTkEKCiMgRGVmaW5lIG5ldyBjYXRlZ29yaWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLnBDUiA9IGNhc2Vfd2hlbigKICAgIGN0RE5BLk1SRCA9PSAiTkVHQVRJVkUiICYgcFQuU3RhZ2U9PSJUMS1UMyIgJiB5cE5TdGF0dXMgPT0gIk4wIiB+ICIxIiwKICAgIGN0RE5BLk1SRCA9PSAiUE9TSVRJVkUiIHwgcFQuU3RhZ2UgPT0gIlQ0IiB8IHlwTlN0YXR1cyA9PSAiTjEtTjMiIH4gIjIiCiAgKSkKCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbIWlzLm5hKGNpcmNfZGF0YSRjdEROQS5wQ1IpLF0Kc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KX5jdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEsIGNvbmYuaW50ID0gMC45NSwgY29uZi50eXBlID0gImxvZy1sb2ciKQpnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCAKICAgICAgICAgICBicmVhay50aW1lLmJ5ID0gMTIsIHBhbGV0dGUgPSBjKCJibHVlIiwgInJlZCIpLCAKICAgICAgICAgICB0aXRsZSA9ICJERlMgLSBjdEROQSBNUkQvQ2xpbmljYWwgQ2hhcmFjdGVyaXN0aWNzIiwgCiAgICAgICAgICAgeWxhYiA9ICJEaXNlYXNlLUZyZWUgU3Vydml2YWwiLCB4bGFiID0gIlRpbWUgZnJvbSBMYW5kbWFyayBUaW1lIHBvaW50IChNb250aHMpIiwgCiAgICAgICAgICAgbGVnZW5kLmxhYnMgPSBjKCJNUkQgbmVnLCBUMS1UMywgTjAiLCAiTVJEIHBvcyBvciBUNCBvciBOMS1OMyIpLCAKICAgICAgICAgICBsZWdlbmQudGl0bGUgPSAiIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXMgPSBjKDAsIDI0KSkKY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLnBDUiwgbGV2ZWxzPWMoIjEiLCIyIiksIGxhYmVscz1jKCJNUkQgbmVnLCBUMS1UMywgTjAiLCJNUkQgcG9zIG9yIFQ0IG9yIE4xLU4zIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5wQ1IsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgojT1MgYnkgY3RETkEgYXQgdGhlIE1SRCBXaW5kb3cgJiB5cFROIENoYXJhY3RlcmlzdGljcwpgYGB7cn0KIyBDbGVhciB3b3Jrc3BhY2UgYW5kIHNldCB3b3JraW5nIGRpcmVjdG9yeQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkID09IFRSVUUsXQpjaXJjX2RhdGEkRlUubW9udGhzIDwtIGNpcmNfZGF0YSRGVS5tb250aHMgLSAzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEZVLm1vbnRocyA+PSAwLF0KY2lyY19kYXRhJGN0RE5BLnBDUiA8LSBOQQoKIyBEZWZpbmUgbmV3IGNhdGVnb3JpZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEucENSID0gY2FzZV93aGVuKAogICAgY3RETkEuTVJEID09ICJORUdBVElWRSIgJiBwVC5TdGFnZT09IlQxLVQzIiAmIHlwTlN0YXR1cyA9PSAiTjAiIH4gIjEiLAogICAgY3RETkEuTVJEID09ICJQT1NJVElWRSIgfCBwVC5TdGFnZSA9PSAiVDQiIHwgeXBOU3RhdHVzID09ICJOMS1OMyIgfiAiMiIKICApKQoKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVshaXMubmEoY2lyY19kYXRhJGN0RE5BLnBDUiksXQpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5wQ1IsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEucENSLCBkYXRhID0gY2lyY19kYXRhLCBjb25mLmludCA9IDAuOTUsIGNvbmYudHlwZSA9ICJsb2ctbG9nIikKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgCiAgICAgICAgICAgYnJlYWsudGltZS5ieSA9IDEyLCBwYWxldHRlID0gYygiYmx1ZSIsICJyZWQiKSwgCiAgICAgICAgICAgdGl0bGUgPSAiT1MgLSBjdEROQSBNUkQvQ2xpbmljYWwgQ2hhcmFjdGVyaXN0aWNzIiwgCiAgICAgICAgICAgeWxhYiA9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYiA9ICJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIAogICAgICAgICAgIGxlZ2VuZC5sYWJzID0gYygiTVJEIG5lZywgVDEtVDMsIE4wIiwgIk1SRCBwb3Mgb3IgVDQgb3IgTjEtTjMiKSwgCiAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gIiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzID0gYygwLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5wQ1IgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5wQ1IsIGxldmVscz1jKCIxIiwiMiIpLCBsYWJlbHM9YygiTVJEIG5lZywgVDEtVDMsIE4wIiwiTVJEIHBvcyBvciBUNCBvciBOMS1OMyIpKQpjb3hfZml0IDwtIGNveHBoZihzdXJ2X29iamVjdCB+IGN0RE5BLnBDUiwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKYGBgCgojTXVsdGl2YXJpYXRlIGNveCByZWdyZXNzaW9uIGZvciBSRlMgLSBjdEROQSBNUkQgV2luZG93CmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiUExBR0FTVF9DbGluaWNhbCBEYXRhLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJEluY2x1ZGVkPT1UUlVFLF0KY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEIT0iIixdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSwgbGFiZWxzID0gYygiTmVnYXRpdmUiLCAiUG9zaXRpdmUiKSkKY2lyY19kYXRhJFByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkUHJpbVNpdGUsIGxldmVscz1jKCJHL0oiLCJTdG9tYWNoIikpCmNpcmNfZGF0YSRHZW5kZXIgPC0gZmFjdG9yKGNpcmNfZGF0YSRHZW5kZXIsIGxldmVscz1jKCJNYWxlIiwiRmVtYWxlIikpCmNpcmNfZGF0YSRBZ2UuR3JvdXAgPC0gZmFjdG9yKGNpcmNfZGF0YSRBZ2UuR3JvdXAsIGxldmVscz1jKCIyIiwiMSIpLCBsYWJlbHMgPSBjKCI+NzAiLCAi4omkNzAiKSkKY2lyY19kYXRhJHBULlN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkcFQuU3RhZ2UsIGxldmVscz1jKCJUMS1UMyIsIlQ0IikpCmNpcmNfZGF0YSR5cE5TdGF0dXMgPC0gZmFjdG9yKGNpcmNfZGF0YSR5cE5TdGF0dXMsIGxldmVscz1jKCJOMCIsIk4xLU4zIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscz1jKCJUUkcxLzIvMyIsIlRSRzQvNSIpKQpzdXJ2X29iamVjdCA8LSBTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkREZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkREZTLkV2ZW50KSAKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCArIFByaW1TaXRlICsgQWdlLkdyb3VwICsgcFQuU3RhZ2UgKyB5cE5TdGF0dXMgKyBUUkcsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCwgZGF0YSA9IGNpcmNfZGF0YSwgbWFpbiA9ICJNdWx0aXZhcmlhdGUgUmVncmVzc2lvbiBNb2RlbCBmb3IgUkZTIiwgcmVmTGFiZWwgPSAiUmVmZXJlbmNlIEdyb3VwIikKdGVzdC5waCA8LSBjb3guenBoKGNveF9maXQpCmBgYAoKCiNNdWx0aXZhcmlhdGUgY294IHJlZ3Jlc3Npb24gZm9yIE9TIC0gY3RETkEgTVJEIFdpbmRvdyB2MQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRCE9IiIsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCmNpcmNfZGF0YSRjdEROQS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5NUkQsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIiksIGxhYmVscyA9IGMoIk5lZ2F0aXZlIiwgIlBvc2l0aXZlIikpCmNpcmNfZGF0YSRQcmltU2l0ZSA8LSBmYWN0b3IoY2lyY19kYXRhJFByaW1TaXRlLCBsZXZlbHM9YygiRy9KIiwiU3RvbWFjaCIpKQpjaXJjX2RhdGEkR2VuZGVyIDwtIGZhY3RvcihjaXJjX2RhdGEkR2VuZGVyLCBsZXZlbHM9YygiTWFsZSIsIkZlbWFsZSIpKQpjaXJjX2RhdGEkQWdlLkdyb3VwIDwtIGZhY3RvcihjaXJjX2RhdGEkQWdlLkdyb3VwLCBsZXZlbHM9YygiMiIsIjEiKSwgbGFiZWxzID0gYygiPjcwIiwgIuKJpDcwIikpCmNpcmNfZGF0YSR5cE5TdGF0dXMgPC0gZmFjdG9yKGNpcmNfZGF0YSR5cE5TdGF0dXMsIGxldmVscz1jKCJOMCIsIk4xLU4zIikpCmNpcmNfZGF0YSRUUkcgPC0gZmFjdG9yKGNpcmNfZGF0YSRUUkcsIGxldmVscz1jKCJUUkcxLzIvMyIsIlRSRzQvNSIpKQpzdXJ2X29iamVjdCA8LSBTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkRlUubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkgCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQgKyBQcmltU2l0ZSArIEdlbmRlciArIEFnZS5Hcm91cCArIHlwTlN0YXR1cyArIFRSRywgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LCBkYXRhID0gY2lyY19kYXRhLCBtYWluID0gIk11bHRpdmFyaWF0ZSBSZWdyZXNzaW9uIE1vZGVsIGZvciBPUyIsIHJlZkxhYmVsID0gIlJlZmVyZW5jZSBHcm91cCIpCnRlc3QucGggPC0gY294LnpwaChjb3hfZml0KQpgYGAKCgojTXVsdGl2YXJpYXRlIGNveCByZWdyZXNzaW9uIGZvciBPUyAtIGN0RE5BIE1SRCBXaW5kb3cgdjIKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJOZWdhdGl2ZSIsICJQb3NpdGl2ZSIpKQpjaXJjX2RhdGEkUHJpbVNpdGUgPC0gZmFjdG9yKGNpcmNfZGF0YSRQcmltU2l0ZSwgbGV2ZWxzPWMoIkcvSiIsIlN0b21hY2giKSkKY2lyY19kYXRhJEdlbmRlciA8LSBmYWN0b3IoY2lyY19kYXRhJEdlbmRlciwgbGV2ZWxzPWMoIk1hbGUiLCJGZW1hbGUiKSkKY2lyY19kYXRhJEFnZS5Hcm91cCA8LSBmYWN0b3IoY2lyY19kYXRhJEFnZS5Hcm91cCwgbGV2ZWxzPWMoIjIiLCIxIiksIGxhYmVscyA9IGMoIj43MCIsICLiiaQ3MCIpKQpjaXJjX2RhdGEkcFQuU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRwVC5TdGFnZSwgbGV2ZWxzPWMoIlQxLVQzIiwiVDQiKSkKY2lyY19kYXRhJHlwTlN0YXR1cyA8LSBmYWN0b3IoY2lyY19kYXRhJHlwTlN0YXR1cywgbGV2ZWxzPWMoIk4wIiwiTjEtTjMiKSkKY2lyY19kYXRhJFRSRyA8LSBmYWN0b3IoY2lyY19kYXRhJFRSRywgbGV2ZWxzPWMoIlRSRzEvMi8zIiwiVFJHNC81IikpCnN1cnZfb2JqZWN0IDwtIFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KSAKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCArIFByaW1TaXRlICsgQWdlLkdyb3VwICsgcFQuU3RhZ2UgKyB5cE5TdGF0dXMgKyBUUkcsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCwgZGF0YSA9IGNpcmNfZGF0YSwgbWFpbiA9ICJNdWx0aXZhcmlhdGUgUmVncmVzc2lvbiBNb2RlbCBmb3IgT1MiLCByZWZMYWJlbCA9ICJSZWZlcmVuY2UgR3JvdXAiKQp0ZXN0LnBoIDwtIGNveC56cGgoY294X2ZpdCkKYGBgCgojREZTIGJ5IGN0RE5BIGF0IHRoZSBTdXJ2ZWlsbGFuY2UgV2luZG93IC0gYWxsIHN0YWdlcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIlBMQUdBU1RfQ2xpbmljYWwgRGF0YS5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRJbmNsdWRlZD09VFJVRSxdCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLnN1cnZlaWxsYW5jZSE9IiIsXQpjaXJjX2RhdGEkREZTLm1vbnRocz1jaXJjX2RhdGEkREZTLm1vbnRocy0zCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJERGUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJERGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJERGUy5FdmVudCl+Y3RETkEuc3VydmVpbGxhbmNlLCBkYXRhID0gY2lyY19kYXRhKQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRERlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRERlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJSRlMgLSBjdEROQSBTdXJ2ZWlsbGFuY2Ugd2luZG93IHwgQWxsIHB0cyIsIHlsYWI9ICJSZWN1cnJlbmNlLUZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuc3VydmVpbGxhbmNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCiNPUyBieSBjdEROQSBhdCB0aGUgU3VydmVpbGxhbmNlIFdpbmRvdyAtIGFsbCBzdGFnZXMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJQTEFHQVNUX0NsaW5pY2FsIERhdGEuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkSW5jbHVkZWQ9PVRSVUUsXQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5zdXJ2ZWlsbGFuY2UhPSIiLF0KY2lyY19kYXRhJEZVLm1vbnRocz1jaXJjX2RhdGEkRlUubW9udGhzLTMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkRlUubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRGVS5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGEgPSBjaXJjX2RhdGEpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJEZVLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5zdXJ2ZWlsbGFuY2UsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIFN1cnZlaWxsYW5jZSB3aW5kb3cgfCBBbGwgcHRzIiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gTGFuZG1hcmsgVGltZSBwb2ludCAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMjQpKQpjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuc3VydmVpbGxhbmNlLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuc3VydmVpbGxhbmNlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgoKCg==